##// END OF EJS Templates
ui: dropped the custom font in favor of builtin ones....
marcink -
r3164:9a2c9ca9 default
parent child Browse files
Show More
@@ -1,53 +1,52 b''
1 # top level files
1 # top level files
2
2
3 include MANIFEST.in
3 include MANIFEST.in
4 include README.rst
4 include README.rst
5 include CHANGES.rst
5 include CHANGES.rst
6 include LICENSE.txt
6 include LICENSE.txt
7
7
8 include rhodecode/VERSION
8 include rhodecode/VERSION
9
9
10 # docs
10 # docs
11 recursive-include docs *
11 recursive-include docs *
12
12
13 # all config files
13 # all config files
14 recursive-include configs *
14 recursive-include configs *
15
15
16 # translations
16 # translations
17 recursive-include rhodecode/i18n *
17 recursive-include rhodecode/i18n *
18
18
19 # non-python core stuff
19 # non-python core stuff
20 recursive-include rhodecode *.cfg
20 recursive-include rhodecode *.cfg
21 recursive-include rhodecode *.json
21 recursive-include rhodecode *.json
22 recursive-include rhodecode *.ini_tmpl
22 recursive-include rhodecode *.ini_tmpl
23 recursive-include rhodecode *.sh
23 recursive-include rhodecode *.sh
24 recursive-include rhodecode *.mako
24 recursive-include rhodecode *.mako
25
25
26 # 502 page
26 # 502 page
27 include rhodecode/public/502.html
27 include rhodecode/public/502.html
28
28
29 # robots
29 # robots
30 include rhodecode/public/robots.txt
30 include rhodecode/public/robots.txt
31
31
32 # images, css
32 # images, css
33 include rhodecode/public/css/*.css
33 include rhodecode/public/css/*.css
34 include rhodecode/public/images/*.*
34 include rhodecode/public/images/*.*
35 include rhodecode/public/images/ee_features/*.*
35 include rhodecode/public/images/ee_features/*.*
36
36
37 # sound files
37 # sound files
38 include rhodecode/public/sounds/*.mp3
38 include rhodecode/public/sounds/*.mp3
39 include rhodecode/public/sounds/*.wav
39 include rhodecode/public/sounds/*.wav
40
40
41 # fonts
41 # fonts
42 recursive-include rhodecode/public/fonts/ProximaNova *
43 recursive-include rhodecode/public/fonts/RCIcons *
42 recursive-include rhodecode/public/fonts/RCIcons *
44
43
45 # js
44 # js
46 recursive-include rhodecode/public/js *
45 recursive-include rhodecode/public/js *
47
46
48 # templates
47 # templates
49 recursive-include rhodecode/templates *
48 recursive-include rhodecode/templates *
50
49
51 # skip any tests files
50 # skip any tests files
52 recursive-exclude rhodecode/tests *
51 recursive-exclude rhodecode/tests *
53
52
@@ -1,13 +1,13 b''
1 .menuselection, .guilabel {
1 .menuselection, .guilabel {
2 font-size: .90em;
2 font-size: .90em;
3 font-family: "proximanovaregular", "Proxima Nova Regular", "Proxima Nova", sans-serif;
3 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
4 font-style: oblique;
4 font-style: oblique;
5 }
5 }
6
6
7 .version{
7 .version {
8 display: none;
8 display: none;
9 }
9 }
10
10
11 .pre{
11 .pre {
12 color:#000
12 color: #000
13 }
13 }
@@ -1,2105 +1,2108 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 """
21 """
22 Helper functions
22 Helper functions
23
23
24 Consists of functions to typically be used within templates, but also
24 Consists of functions to typically be used within templates, but also
25 available to Controllers. This module is available to both as 'h'.
25 available to Controllers. This module is available to both as 'h'.
26 """
26 """
27
27
28 import os
28 import os
29 import random
29 import random
30 import hashlib
30 import hashlib
31 import StringIO
31 import StringIO
32 import textwrap
32 import textwrap
33 import urllib
33 import urllib
34 import math
34 import math
35 import logging
35 import logging
36 import re
36 import re
37 import urlparse
37 import urlparse
38 import time
38 import time
39 import string
39 import string
40 import hashlib
40 import hashlib
41 from collections import OrderedDict
41 from collections import OrderedDict
42
42
43 import pygments
43 import pygments
44 import itertools
44 import itertools
45 import fnmatch
45 import fnmatch
46 import bleach
46 import bleach
47
47
48 from datetime import datetime
48 from datetime import datetime
49 from functools import partial
49 from functools import partial
50 from pygments.formatters.html import HtmlFormatter
50 from pygments.formatters.html import HtmlFormatter
51 from pygments import highlight as code_highlight
51 from pygments import highlight as code_highlight
52 from pygments.lexers import (
52 from pygments.lexers import (
53 get_lexer_by_name, get_lexer_for_filename, get_lexer_for_mimetype)
53 get_lexer_by_name, get_lexer_for_filename, get_lexer_for_mimetype)
54
54
55 from pyramid.threadlocal import get_current_request
55 from pyramid.threadlocal import get_current_request
56
56
57 from webhelpers.html import literal, HTML, escape
57 from webhelpers.html import literal, HTML, escape
58 from webhelpers.html.tools import *
58 from webhelpers.html.tools import *
59 from webhelpers.html.builder import make_tag
59 from webhelpers.html.builder import make_tag
60 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
60 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
61 end_form, file, form as wh_form, hidden, image, javascript_link, link_to, \
61 end_form, file, form as wh_form, hidden, image, javascript_link, link_to, \
62 link_to_if, link_to_unless, ol, required_legend, select, stylesheet_link, \
62 link_to_if, link_to_unless, ol, required_legend, select, stylesheet_link, \
63 submit, text, password, textarea, title, ul, xml_declaration, radio
63 submit, text, password, textarea, title, ul, xml_declaration, radio
64 from webhelpers.html.tools import auto_link, button_to, highlight, \
64 from webhelpers.html.tools import auto_link, button_to, highlight, \
65 js_obfuscate, mail_to, strip_links, strip_tags, tag_re
65 js_obfuscate, mail_to, strip_links, strip_tags, tag_re
66 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
66 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
67 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
67 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
68 replace_whitespace, urlify, truncate, wrap_paragraphs
68 replace_whitespace, urlify, truncate, wrap_paragraphs
69 from webhelpers.date import time_ago_in_words
69 from webhelpers.date import time_ago_in_words
70 from webhelpers.paginate import Page as _Page
70 from webhelpers.paginate import Page as _Page
71 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
71 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
72 convert_boolean_attrs, NotGiven, _make_safe_id_component
72 convert_boolean_attrs, NotGiven, _make_safe_id_component
73 from webhelpers2.number import format_byte_size
73 from webhelpers2.number import format_byte_size
74
74
75 from rhodecode.lib.action_parser import action_parser
75 from rhodecode.lib.action_parser import action_parser
76 from rhodecode.lib.ext_json import json
76 from rhodecode.lib.ext_json import json
77 from rhodecode.lib.utils import repo_name_slug, get_custom_lexer
77 from rhodecode.lib.utils import repo_name_slug, get_custom_lexer
78 from rhodecode.lib.utils2 import str2bool, safe_unicode, safe_str, \
78 from rhodecode.lib.utils2 import str2bool, safe_unicode, safe_str, \
79 get_commit_safe, datetime_to_time, time_to_datetime, time_to_utcdatetime, \
79 get_commit_safe, datetime_to_time, time_to_datetime, time_to_utcdatetime, \
80 AttributeDict, safe_int, md5, md5_safe
80 AttributeDict, safe_int, md5, md5_safe
81 from rhodecode.lib.markup_renderer import MarkupRenderer, relative_links
81 from rhodecode.lib.markup_renderer import MarkupRenderer, relative_links
82 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
82 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
83 from rhodecode.lib.vcs.backends.base import BaseChangeset, EmptyCommit
83 from rhodecode.lib.vcs.backends.base import BaseChangeset, EmptyCommit
84 from rhodecode.config.conf import DATE_FORMAT, DATETIME_FORMAT
84 from rhodecode.config.conf import DATE_FORMAT, DATETIME_FORMAT
85 from rhodecode.model.changeset_status import ChangesetStatusModel
85 from rhodecode.model.changeset_status import ChangesetStatusModel
86 from rhodecode.model.db import Permission, User, Repository
86 from rhodecode.model.db import Permission, User, Repository
87 from rhodecode.model.repo_group import RepoGroupModel
87 from rhodecode.model.repo_group import RepoGroupModel
88 from rhodecode.model.settings import IssueTrackerSettingsModel
88 from rhodecode.model.settings import IssueTrackerSettingsModel
89
89
90 log = logging.getLogger(__name__)
90 log = logging.getLogger(__name__)
91
91
92
92
93 DEFAULT_USER = User.DEFAULT_USER
93 DEFAULT_USER = User.DEFAULT_USER
94 DEFAULT_USER_EMAIL = User.DEFAULT_USER_EMAIL
94 DEFAULT_USER_EMAIL = User.DEFAULT_USER_EMAIL
95
95
96
96
97 def asset(path, ver=None, **kwargs):
97 def asset(path, ver=None, **kwargs):
98 """
98 """
99 Helper to generate a static asset file path for rhodecode assets
99 Helper to generate a static asset file path for rhodecode assets
100
100
101 eg. h.asset('images/image.png', ver='3923')
101 eg. h.asset('images/image.png', ver='3923')
102
102
103 :param path: path of asset
103 :param path: path of asset
104 :param ver: optional version query param to append as ?ver=
104 :param ver: optional version query param to append as ?ver=
105 """
105 """
106 request = get_current_request()
106 request = get_current_request()
107 query = {}
107 query = {}
108 query.update(kwargs)
108 query.update(kwargs)
109 if ver:
109 if ver:
110 query = {'ver': ver}
110 query = {'ver': ver}
111 return request.static_path(
111 return request.static_path(
112 'rhodecode:public/{}'.format(path), _query=query)
112 'rhodecode:public/{}'.format(path), _query=query)
113
113
114
114
115 default_html_escape_table = {
115 default_html_escape_table = {
116 ord('&'): u'&amp;',
116 ord('&'): u'&amp;',
117 ord('<'): u'&lt;',
117 ord('<'): u'&lt;',
118 ord('>'): u'&gt;',
118 ord('>'): u'&gt;',
119 ord('"'): u'&quot;',
119 ord('"'): u'&quot;',
120 ord("'"): u'&#39;',
120 ord("'"): u'&#39;',
121 }
121 }
122
122
123
123
124 def html_escape(text, html_escape_table=default_html_escape_table):
124 def html_escape(text, html_escape_table=default_html_escape_table):
125 """Produce entities within text."""
125 """Produce entities within text."""
126 return text.translate(html_escape_table)
126 return text.translate(html_escape_table)
127
127
128
128
129 def chop_at_smart(s, sub, inclusive=False, suffix_if_chopped=None):
129 def chop_at_smart(s, sub, inclusive=False, suffix_if_chopped=None):
130 """
130 """
131 Truncate string ``s`` at the first occurrence of ``sub``.
131 Truncate string ``s`` at the first occurrence of ``sub``.
132
132
133 If ``inclusive`` is true, truncate just after ``sub`` rather than at it.
133 If ``inclusive`` is true, truncate just after ``sub`` rather than at it.
134 """
134 """
135 suffix_if_chopped = suffix_if_chopped or ''
135 suffix_if_chopped = suffix_if_chopped or ''
136 pos = s.find(sub)
136 pos = s.find(sub)
137 if pos == -1:
137 if pos == -1:
138 return s
138 return s
139
139
140 if inclusive:
140 if inclusive:
141 pos += len(sub)
141 pos += len(sub)
142
142
143 chopped = s[:pos]
143 chopped = s[:pos]
144 left = s[pos:].strip()
144 left = s[pos:].strip()
145
145
146 if left and suffix_if_chopped:
146 if left and suffix_if_chopped:
147 chopped += suffix_if_chopped
147 chopped += suffix_if_chopped
148
148
149 return chopped
149 return chopped
150
150
151
151
152 def shorter(text, size=20):
152 def shorter(text, size=20):
153 postfix = '...'
153 postfix = '...'
154 if len(text) > size:
154 if len(text) > size:
155 return text[:size - len(postfix)] + postfix
155 return text[:size - len(postfix)] + postfix
156 return text
156 return text
157
157
158
158
159 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
159 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
160 """
160 """
161 Reset button
161 Reset button
162 """
162 """
163 _set_input_attrs(attrs, type, name, value)
163 _set_input_attrs(attrs, type, name, value)
164 _set_id_attr(attrs, id, name)
164 _set_id_attr(attrs, id, name)
165 convert_boolean_attrs(attrs, ["disabled"])
165 convert_boolean_attrs(attrs, ["disabled"])
166 return HTML.input(**attrs)
166 return HTML.input(**attrs)
167
167
168 reset = _reset
168 reset = _reset
169 safeid = _make_safe_id_component
169 safeid = _make_safe_id_component
170
170
171
171
172 def branding(name, length=40):
172 def branding(name, length=40):
173 return truncate(name, length, indicator="")
173 return truncate(name, length, indicator="")
174
174
175
175
176 def FID(raw_id, path):
176 def FID(raw_id, path):
177 """
177 """
178 Creates a unique ID for filenode based on it's hash of path and commit
178 Creates a unique ID for filenode based on it's hash of path and commit
179 it's safe to use in urls
179 it's safe to use in urls
180
180
181 :param raw_id:
181 :param raw_id:
182 :param path:
182 :param path:
183 """
183 """
184
184
185 return 'c-%s-%s' % (short_id(raw_id), md5_safe(path)[:12])
185 return 'c-%s-%s' % (short_id(raw_id), md5_safe(path)[:12])
186
186
187
187
188 class _GetError(object):
188 class _GetError(object):
189 """Get error from form_errors, and represent it as span wrapped error
189 """Get error from form_errors, and represent it as span wrapped error
190 message
190 message
191
191
192 :param field_name: field to fetch errors for
192 :param field_name: field to fetch errors for
193 :param form_errors: form errors dict
193 :param form_errors: form errors dict
194 """
194 """
195
195
196 def __call__(self, field_name, form_errors):
196 def __call__(self, field_name, form_errors):
197 tmpl = """<span class="error_msg">%s</span>"""
197 tmpl = """<span class="error_msg">%s</span>"""
198 if form_errors and field_name in form_errors:
198 if form_errors and field_name in form_errors:
199 return literal(tmpl % form_errors.get(field_name))
199 return literal(tmpl % form_errors.get(field_name))
200
200
201 get_error = _GetError()
201 get_error = _GetError()
202
202
203
203
204 class _ToolTip(object):
204 class _ToolTip(object):
205
205
206 def __call__(self, tooltip_title, trim_at=50):
206 def __call__(self, tooltip_title, trim_at=50):
207 """
207 """
208 Special function just to wrap our text into nice formatted
208 Special function just to wrap our text into nice formatted
209 autowrapped text
209 autowrapped text
210
210
211 :param tooltip_title:
211 :param tooltip_title:
212 """
212 """
213 tooltip_title = escape(tooltip_title)
213 tooltip_title = escape(tooltip_title)
214 tooltip_title = tooltip_title.replace('<', '&lt;').replace('>', '&gt;')
214 tooltip_title = tooltip_title.replace('<', '&lt;').replace('>', '&gt;')
215 return tooltip_title
215 return tooltip_title
216 tooltip = _ToolTip()
216 tooltip = _ToolTip()
217
217
218
218
219 def files_breadcrumbs(repo_name, commit_id, file_path):
219 def files_breadcrumbs(repo_name, commit_id, file_path):
220 if isinstance(file_path, str):
220 if isinstance(file_path, str):
221 file_path = safe_unicode(file_path)
221 file_path = safe_unicode(file_path)
222
222
223 # TODO: johbo: Is this always a url like path, or is this operating
223 # TODO: johbo: Is this always a url like path, or is this operating
224 # system dependent?
224 # system dependent?
225 path_segments = file_path.split('/')
225 path_segments = file_path.split('/')
226
226
227 repo_name_html = escape(repo_name)
227 repo_name_html = escape(repo_name)
228 if len(path_segments) == 1 and path_segments[0] == '':
228 if len(path_segments) == 1 and path_segments[0] == '':
229 url_segments = [repo_name_html]
229 url_segments = [repo_name_html]
230 else:
230 else:
231 url_segments = [
231 url_segments = [
232 link_to(
232 link_to(
233 repo_name_html,
233 repo_name_html,
234 route_path(
234 route_path(
235 'repo_files',
235 'repo_files',
236 repo_name=repo_name,
236 repo_name=repo_name,
237 commit_id=commit_id,
237 commit_id=commit_id,
238 f_path=''),
238 f_path=''),
239 class_='pjax-link')]
239 class_='pjax-link')]
240
240
241 last_cnt = len(path_segments) - 1
241 last_cnt = len(path_segments) - 1
242 for cnt, segment in enumerate(path_segments):
242 for cnt, segment in enumerate(path_segments):
243 if not segment:
243 if not segment:
244 continue
244 continue
245 segment_html = escape(segment)
245 segment_html = escape(segment)
246
246
247 if cnt != last_cnt:
247 if cnt != last_cnt:
248 url_segments.append(
248 url_segments.append(
249 link_to(
249 link_to(
250 segment_html,
250 segment_html,
251 route_path(
251 route_path(
252 'repo_files',
252 'repo_files',
253 repo_name=repo_name,
253 repo_name=repo_name,
254 commit_id=commit_id,
254 commit_id=commit_id,
255 f_path='/'.join(path_segments[:cnt + 1])),
255 f_path='/'.join(path_segments[:cnt + 1])),
256 class_='pjax-link'))
256 class_='pjax-link'))
257 else:
257 else:
258 url_segments.append(segment_html)
258 url_segments.append(segment_html)
259
259
260 return literal('/'.join(url_segments))
260 return literal('/'.join(url_segments))
261
261
262
262
263 class CodeHtmlFormatter(HtmlFormatter):
263 class CodeHtmlFormatter(HtmlFormatter):
264 """
264 """
265 My code Html Formatter for source codes
265 My code Html Formatter for source codes
266 """
266 """
267
267
268 def wrap(self, source, outfile):
268 def wrap(self, source, outfile):
269 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
269 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
270
270
271 def _wrap_code(self, source):
271 def _wrap_code(self, source):
272 for cnt, it in enumerate(source):
272 for cnt, it in enumerate(source):
273 i, t = it
273 i, t = it
274 t = '<div id="L%s">%s</div>' % (cnt + 1, t)
274 t = '<div id="L%s">%s</div>' % (cnt + 1, t)
275 yield i, t
275 yield i, t
276
276
277 def _wrap_tablelinenos(self, inner):
277 def _wrap_tablelinenos(self, inner):
278 dummyoutfile = StringIO.StringIO()
278 dummyoutfile = StringIO.StringIO()
279 lncount = 0
279 lncount = 0
280 for t, line in inner:
280 for t, line in inner:
281 if t:
281 if t:
282 lncount += 1
282 lncount += 1
283 dummyoutfile.write(line)
283 dummyoutfile.write(line)
284
284
285 fl = self.linenostart
285 fl = self.linenostart
286 mw = len(str(lncount + fl - 1))
286 mw = len(str(lncount + fl - 1))
287 sp = self.linenospecial
287 sp = self.linenospecial
288 st = self.linenostep
288 st = self.linenostep
289 la = self.lineanchors
289 la = self.lineanchors
290 aln = self.anchorlinenos
290 aln = self.anchorlinenos
291 nocls = self.noclasses
291 nocls = self.noclasses
292 if sp:
292 if sp:
293 lines = []
293 lines = []
294
294
295 for i in range(fl, fl + lncount):
295 for i in range(fl, fl + lncount):
296 if i % st == 0:
296 if i % st == 0:
297 if i % sp == 0:
297 if i % sp == 0:
298 if aln:
298 if aln:
299 lines.append('<a href="#%s%d" class="special">%*d</a>' %
299 lines.append('<a href="#%s%d" class="special">%*d</a>' %
300 (la, i, mw, i))
300 (la, i, mw, i))
301 else:
301 else:
302 lines.append('<span class="special">%*d</span>' % (mw, i))
302 lines.append('<span class="special">%*d</span>' % (mw, i))
303 else:
303 else:
304 if aln:
304 if aln:
305 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
305 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
306 else:
306 else:
307 lines.append('%*d' % (mw, i))
307 lines.append('%*d' % (mw, i))
308 else:
308 else:
309 lines.append('')
309 lines.append('')
310 ls = '\n'.join(lines)
310 ls = '\n'.join(lines)
311 else:
311 else:
312 lines = []
312 lines = []
313 for i in range(fl, fl + lncount):
313 for i in range(fl, fl + lncount):
314 if i % st == 0:
314 if i % st == 0:
315 if aln:
315 if aln:
316 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
316 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
317 else:
317 else:
318 lines.append('%*d' % (mw, i))
318 lines.append('%*d' % (mw, i))
319 else:
319 else:
320 lines.append('')
320 lines.append('')
321 ls = '\n'.join(lines)
321 ls = '\n'.join(lines)
322
322
323 # in case you wonder about the seemingly redundant <div> here: since the
323 # in case you wonder about the seemingly redundant <div> here: since the
324 # content in the other cell also is wrapped in a div, some browsers in
324 # content in the other cell also is wrapped in a div, some browsers in
325 # some configurations seem to mess up the formatting...
325 # some configurations seem to mess up the formatting...
326 if nocls:
326 if nocls:
327 yield 0, ('<table class="%stable">' % self.cssclass +
327 yield 0, ('<table class="%stable">' % self.cssclass +
328 '<tr><td><div class="linenodiv" '
328 '<tr><td><div class="linenodiv" '
329 'style="background-color: #f0f0f0; padding-right: 10px">'
329 'style="background-color: #f0f0f0; padding-right: 10px">'
330 '<pre style="line-height: 125%">' +
330 '<pre style="line-height: 125%">' +
331 ls + '</pre></div></td><td id="hlcode" class="code">')
331 ls + '</pre></div></td><td id="hlcode" class="code">')
332 else:
332 else:
333 yield 0, ('<table class="%stable">' % self.cssclass +
333 yield 0, ('<table class="%stable">' % self.cssclass +
334 '<tr><td class="linenos"><div class="linenodiv"><pre>' +
334 '<tr><td class="linenos"><div class="linenodiv"><pre>' +
335 ls + '</pre></div></td><td id="hlcode" class="code">')
335 ls + '</pre></div></td><td id="hlcode" class="code">')
336 yield 0, dummyoutfile.getvalue()
336 yield 0, dummyoutfile.getvalue()
337 yield 0, '</td></tr></table>'
337 yield 0, '</td></tr></table>'
338
338
339
339
340 class SearchContentCodeHtmlFormatter(CodeHtmlFormatter):
340 class SearchContentCodeHtmlFormatter(CodeHtmlFormatter):
341 def __init__(self, **kw):
341 def __init__(self, **kw):
342 # only show these line numbers if set
342 # only show these line numbers if set
343 self.only_lines = kw.pop('only_line_numbers', [])
343 self.only_lines = kw.pop('only_line_numbers', [])
344 self.query_terms = kw.pop('query_terms', [])
344 self.query_terms = kw.pop('query_terms', [])
345 self.max_lines = kw.pop('max_lines', 5)
345 self.max_lines = kw.pop('max_lines', 5)
346 self.line_context = kw.pop('line_context', 3)
346 self.line_context = kw.pop('line_context', 3)
347 self.url = kw.pop('url', None)
347 self.url = kw.pop('url', None)
348
348
349 super(CodeHtmlFormatter, self).__init__(**kw)
349 super(CodeHtmlFormatter, self).__init__(**kw)
350
350
351 def _wrap_code(self, source):
351 def _wrap_code(self, source):
352 for cnt, it in enumerate(source):
352 for cnt, it in enumerate(source):
353 i, t = it
353 i, t = it
354 t = '<pre>%s</pre>' % t
354 t = '<pre>%s</pre>' % t
355 yield i, t
355 yield i, t
356
356
357 def _wrap_tablelinenos(self, inner):
357 def _wrap_tablelinenos(self, inner):
358 yield 0, '<table class="code-highlight %stable">' % self.cssclass
358 yield 0, '<table class="code-highlight %stable">' % self.cssclass
359
359
360 last_shown_line_number = 0
360 last_shown_line_number = 0
361 current_line_number = 1
361 current_line_number = 1
362
362
363 for t, line in inner:
363 for t, line in inner:
364 if not t:
364 if not t:
365 yield t, line
365 yield t, line
366 continue
366 continue
367
367
368 if current_line_number in self.only_lines:
368 if current_line_number in self.only_lines:
369 if last_shown_line_number + 1 != current_line_number:
369 if last_shown_line_number + 1 != current_line_number:
370 yield 0, '<tr>'
370 yield 0, '<tr>'
371 yield 0, '<td class="line">...</td>'
371 yield 0, '<td class="line">...</td>'
372 yield 0, '<td id="hlcode" class="code"></td>'
372 yield 0, '<td id="hlcode" class="code"></td>'
373 yield 0, '</tr>'
373 yield 0, '</tr>'
374
374
375 yield 0, '<tr>'
375 yield 0, '<tr>'
376 if self.url:
376 if self.url:
377 yield 0, '<td class="line"><a href="%s#L%i">%i</a></td>' % (
377 yield 0, '<td class="line"><a href="%s#L%i">%i</a></td>' % (
378 self.url, current_line_number, current_line_number)
378 self.url, current_line_number, current_line_number)
379 else:
379 else:
380 yield 0, '<td class="line"><a href="">%i</a></td>' % (
380 yield 0, '<td class="line"><a href="">%i</a></td>' % (
381 current_line_number)
381 current_line_number)
382 yield 0, '<td id="hlcode" class="code">' + line + '</td>'
382 yield 0, '<td id="hlcode" class="code">' + line + '</td>'
383 yield 0, '</tr>'
383 yield 0, '</tr>'
384
384
385 last_shown_line_number = current_line_number
385 last_shown_line_number = current_line_number
386
386
387 current_line_number += 1
387 current_line_number += 1
388
388
389
389
390 yield 0, '</table>'
390 yield 0, '</table>'
391
391
392
392
393 def extract_phrases(text_query):
393 def extract_phrases(text_query):
394 """
394 """
395 Extracts phrases from search term string making sure phrases
395 Extracts phrases from search term string making sure phrases
396 contained in double quotes are kept together - and discarding empty values
396 contained in double quotes are kept together - and discarding empty values
397 or fully whitespace values eg.
397 or fully whitespace values eg.
398
398
399 'some text "a phrase" more' => ['some', 'text', 'a phrase', 'more']
399 'some text "a phrase" more' => ['some', 'text', 'a phrase', 'more']
400
400
401 """
401 """
402
402
403 in_phrase = False
403 in_phrase = False
404 buf = ''
404 buf = ''
405 phrases = []
405 phrases = []
406 for char in text_query:
406 for char in text_query:
407 if in_phrase:
407 if in_phrase:
408 if char == '"': # end phrase
408 if char == '"': # end phrase
409 phrases.append(buf)
409 phrases.append(buf)
410 buf = ''
410 buf = ''
411 in_phrase = False
411 in_phrase = False
412 continue
412 continue
413 else:
413 else:
414 buf += char
414 buf += char
415 continue
415 continue
416 else:
416 else:
417 if char == '"': # start phrase
417 if char == '"': # start phrase
418 in_phrase = True
418 in_phrase = True
419 phrases.append(buf)
419 phrases.append(buf)
420 buf = ''
420 buf = ''
421 continue
421 continue
422 elif char == ' ':
422 elif char == ' ':
423 phrases.append(buf)
423 phrases.append(buf)
424 buf = ''
424 buf = ''
425 continue
425 continue
426 else:
426 else:
427 buf += char
427 buf += char
428
428
429 phrases.append(buf)
429 phrases.append(buf)
430 phrases = [phrase.strip() for phrase in phrases if phrase.strip()]
430 phrases = [phrase.strip() for phrase in phrases if phrase.strip()]
431 return phrases
431 return phrases
432
432
433
433
434 def get_matching_offsets(text, phrases):
434 def get_matching_offsets(text, phrases):
435 """
435 """
436 Returns a list of string offsets in `text` that the list of `terms` match
436 Returns a list of string offsets in `text` that the list of `terms` match
437
437
438 >>> get_matching_offsets('some text here', ['some', 'here'])
438 >>> get_matching_offsets('some text here', ['some', 'here'])
439 [(0, 4), (10, 14)]
439 [(0, 4), (10, 14)]
440
440
441 """
441 """
442 offsets = []
442 offsets = []
443 for phrase in phrases:
443 for phrase in phrases:
444 for match in re.finditer(phrase, text):
444 for match in re.finditer(phrase, text):
445 offsets.append((match.start(), match.end()))
445 offsets.append((match.start(), match.end()))
446
446
447 return offsets
447 return offsets
448
448
449
449
450 def normalize_text_for_matching(x):
450 def normalize_text_for_matching(x):
451 """
451 """
452 Replaces all non alnum characters to spaces and lower cases the string,
452 Replaces all non alnum characters to spaces and lower cases the string,
453 useful for comparing two text strings without punctuation
453 useful for comparing two text strings without punctuation
454 """
454 """
455 return re.sub(r'[^\w]', ' ', x.lower())
455 return re.sub(r'[^\w]', ' ', x.lower())
456
456
457
457
458 def get_matching_line_offsets(lines, terms):
458 def get_matching_line_offsets(lines, terms):
459 """ Return a set of `lines` indices (starting from 1) matching a
459 """ Return a set of `lines` indices (starting from 1) matching a
460 text search query, along with `context` lines above/below matching lines
460 text search query, along with `context` lines above/below matching lines
461
461
462 :param lines: list of strings representing lines
462 :param lines: list of strings representing lines
463 :param terms: search term string to match in lines eg. 'some text'
463 :param terms: search term string to match in lines eg. 'some text'
464 :param context: number of lines above/below a matching line to add to result
464 :param context: number of lines above/below a matching line to add to result
465 :param max_lines: cut off for lines of interest
465 :param max_lines: cut off for lines of interest
466 eg.
466 eg.
467
467
468 text = '''
468 text = '''
469 words words words
469 words words words
470 words words words
470 words words words
471 some text some
471 some text some
472 words words words
472 words words words
473 words words words
473 words words words
474 text here what
474 text here what
475 '''
475 '''
476 get_matching_line_offsets(text, 'text', context=1)
476 get_matching_line_offsets(text, 'text', context=1)
477 {3: [(5, 9)], 6: [(0, 4)]]
477 {3: [(5, 9)], 6: [(0, 4)]]
478
478
479 """
479 """
480 matching_lines = {}
480 matching_lines = {}
481 phrases = [normalize_text_for_matching(phrase)
481 phrases = [normalize_text_for_matching(phrase)
482 for phrase in extract_phrases(terms)]
482 for phrase in extract_phrases(terms)]
483
483
484 for line_index, line in enumerate(lines, start=1):
484 for line_index, line in enumerate(lines, start=1):
485 match_offsets = get_matching_offsets(
485 match_offsets = get_matching_offsets(
486 normalize_text_for_matching(line), phrases)
486 normalize_text_for_matching(line), phrases)
487 if match_offsets:
487 if match_offsets:
488 matching_lines[line_index] = match_offsets
488 matching_lines[line_index] = match_offsets
489
489
490 return matching_lines
490 return matching_lines
491
491
492
492
493 def hsv_to_rgb(h, s, v):
493 def hsv_to_rgb(h, s, v):
494 """ Convert hsv color values to rgb """
494 """ Convert hsv color values to rgb """
495
495
496 if s == 0.0:
496 if s == 0.0:
497 return v, v, v
497 return v, v, v
498 i = int(h * 6.0) # XXX assume int() truncates!
498 i = int(h * 6.0) # XXX assume int() truncates!
499 f = (h * 6.0) - i
499 f = (h * 6.0) - i
500 p = v * (1.0 - s)
500 p = v * (1.0 - s)
501 q = v * (1.0 - s * f)
501 q = v * (1.0 - s * f)
502 t = v * (1.0 - s * (1.0 - f))
502 t = v * (1.0 - s * (1.0 - f))
503 i = i % 6
503 i = i % 6
504 if i == 0:
504 if i == 0:
505 return v, t, p
505 return v, t, p
506 if i == 1:
506 if i == 1:
507 return q, v, p
507 return q, v, p
508 if i == 2:
508 if i == 2:
509 return p, v, t
509 return p, v, t
510 if i == 3:
510 if i == 3:
511 return p, q, v
511 return p, q, v
512 if i == 4:
512 if i == 4:
513 return t, p, v
513 return t, p, v
514 if i == 5:
514 if i == 5:
515 return v, p, q
515 return v, p, q
516
516
517
517
518 def unique_color_generator(n=10000, saturation=0.10, lightness=0.95):
518 def unique_color_generator(n=10000, saturation=0.10, lightness=0.95):
519 """
519 """
520 Generator for getting n of evenly distributed colors using
520 Generator for getting n of evenly distributed colors using
521 hsv color and golden ratio. It always return same order of colors
521 hsv color and golden ratio. It always return same order of colors
522
522
523 :param n: number of colors to generate
523 :param n: number of colors to generate
524 :param saturation: saturation of returned colors
524 :param saturation: saturation of returned colors
525 :param lightness: lightness of returned colors
525 :param lightness: lightness of returned colors
526 :returns: RGB tuple
526 :returns: RGB tuple
527 """
527 """
528
528
529 golden_ratio = 0.618033988749895
529 golden_ratio = 0.618033988749895
530 h = 0.22717784590367374
530 h = 0.22717784590367374
531
531
532 for _ in xrange(n):
532 for _ in xrange(n):
533 h += golden_ratio
533 h += golden_ratio
534 h %= 1
534 h %= 1
535 HSV_tuple = [h, saturation, lightness]
535 HSV_tuple = [h, saturation, lightness]
536 RGB_tuple = hsv_to_rgb(*HSV_tuple)
536 RGB_tuple = hsv_to_rgb(*HSV_tuple)
537 yield map(lambda x: str(int(x * 256)), RGB_tuple)
537 yield map(lambda x: str(int(x * 256)), RGB_tuple)
538
538
539
539
540 def color_hasher(n=10000, saturation=0.10, lightness=0.95):
540 def color_hasher(n=10000, saturation=0.10, lightness=0.95):
541 """
541 """
542 Returns a function which when called with an argument returns a unique
542 Returns a function which when called with an argument returns a unique
543 color for that argument, eg.
543 color for that argument, eg.
544
544
545 :param n: number of colors to generate
545 :param n: number of colors to generate
546 :param saturation: saturation of returned colors
546 :param saturation: saturation of returned colors
547 :param lightness: lightness of returned colors
547 :param lightness: lightness of returned colors
548 :returns: css RGB string
548 :returns: css RGB string
549
549
550 >>> color_hash = color_hasher()
550 >>> color_hash = color_hasher()
551 >>> color_hash('hello')
551 >>> color_hash('hello')
552 'rgb(34, 12, 59)'
552 'rgb(34, 12, 59)'
553 >>> color_hash('hello')
553 >>> color_hash('hello')
554 'rgb(34, 12, 59)'
554 'rgb(34, 12, 59)'
555 >>> color_hash('other')
555 >>> color_hash('other')
556 'rgb(90, 224, 159)'
556 'rgb(90, 224, 159)'
557 """
557 """
558
558
559 color_dict = {}
559 color_dict = {}
560 cgenerator = unique_color_generator(
560 cgenerator = unique_color_generator(
561 saturation=saturation, lightness=lightness)
561 saturation=saturation, lightness=lightness)
562
562
563 def get_color_string(thing):
563 def get_color_string(thing):
564 if thing in color_dict:
564 if thing in color_dict:
565 col = color_dict[thing]
565 col = color_dict[thing]
566 else:
566 else:
567 col = color_dict[thing] = cgenerator.next()
567 col = color_dict[thing] = cgenerator.next()
568 return "rgb(%s)" % (', '.join(col))
568 return "rgb(%s)" % (', '.join(col))
569
569
570 return get_color_string
570 return get_color_string
571
571
572
572
573 def get_lexer_safe(mimetype=None, filepath=None):
573 def get_lexer_safe(mimetype=None, filepath=None):
574 """
574 """
575 Tries to return a relevant pygments lexer using mimetype/filepath name,
575 Tries to return a relevant pygments lexer using mimetype/filepath name,
576 defaulting to plain text if none could be found
576 defaulting to plain text if none could be found
577 """
577 """
578 lexer = None
578 lexer = None
579 try:
579 try:
580 if mimetype:
580 if mimetype:
581 lexer = get_lexer_for_mimetype(mimetype)
581 lexer = get_lexer_for_mimetype(mimetype)
582 if not lexer:
582 if not lexer:
583 lexer = get_lexer_for_filename(filepath)
583 lexer = get_lexer_for_filename(filepath)
584 except pygments.util.ClassNotFound:
584 except pygments.util.ClassNotFound:
585 pass
585 pass
586
586
587 if not lexer:
587 if not lexer:
588 lexer = get_lexer_by_name('text')
588 lexer = get_lexer_by_name('text')
589
589
590 return lexer
590 return lexer
591
591
592
592
593 def get_lexer_for_filenode(filenode):
593 def get_lexer_for_filenode(filenode):
594 lexer = get_custom_lexer(filenode.extension) or filenode.lexer
594 lexer = get_custom_lexer(filenode.extension) or filenode.lexer
595 return lexer
595 return lexer
596
596
597
597
598 def pygmentize(filenode, **kwargs):
598 def pygmentize(filenode, **kwargs):
599 """
599 """
600 pygmentize function using pygments
600 pygmentize function using pygments
601
601
602 :param filenode:
602 :param filenode:
603 """
603 """
604 lexer = get_lexer_for_filenode(filenode)
604 lexer = get_lexer_for_filenode(filenode)
605 return literal(code_highlight(filenode.content, lexer,
605 return literal(code_highlight(filenode.content, lexer,
606 CodeHtmlFormatter(**kwargs)))
606 CodeHtmlFormatter(**kwargs)))
607
607
608
608
609 def is_following_repo(repo_name, user_id):
609 def is_following_repo(repo_name, user_id):
610 from rhodecode.model.scm import ScmModel
610 from rhodecode.model.scm import ScmModel
611 return ScmModel().is_following_repo(repo_name, user_id)
611 return ScmModel().is_following_repo(repo_name, user_id)
612
612
613
613
614 class _Message(object):
614 class _Message(object):
615 """A message returned by ``Flash.pop_messages()``.
615 """A message returned by ``Flash.pop_messages()``.
616
616
617 Converting the message to a string returns the message text. Instances
617 Converting the message to a string returns the message text. Instances
618 also have the following attributes:
618 also have the following attributes:
619
619
620 * ``message``: the message text.
620 * ``message``: the message text.
621 * ``category``: the category specified when the message was created.
621 * ``category``: the category specified when the message was created.
622 """
622 """
623
623
624 def __init__(self, category, message):
624 def __init__(self, category, message):
625 self.category = category
625 self.category = category
626 self.message = message
626 self.message = message
627
627
628 def __str__(self):
628 def __str__(self):
629 return self.message
629 return self.message
630
630
631 __unicode__ = __str__
631 __unicode__ = __str__
632
632
633 def __html__(self):
633 def __html__(self):
634 return escape(safe_unicode(self.message))
634 return escape(safe_unicode(self.message))
635
635
636
636
637 class Flash(object):
637 class Flash(object):
638 # List of allowed categories. If None, allow any category.
638 # List of allowed categories. If None, allow any category.
639 categories = ["warning", "notice", "error", "success"]
639 categories = ["warning", "notice", "error", "success"]
640
640
641 # Default category if none is specified.
641 # Default category if none is specified.
642 default_category = "notice"
642 default_category = "notice"
643
643
644 def __init__(self, session_key="flash", categories=None,
644 def __init__(self, session_key="flash", categories=None,
645 default_category=None):
645 default_category=None):
646 """
646 """
647 Instantiate a ``Flash`` object.
647 Instantiate a ``Flash`` object.
648
648
649 ``session_key`` is the key to save the messages under in the user's
649 ``session_key`` is the key to save the messages under in the user's
650 session.
650 session.
651
651
652 ``categories`` is an optional list which overrides the default list
652 ``categories`` is an optional list which overrides the default list
653 of categories.
653 of categories.
654
654
655 ``default_category`` overrides the default category used for messages
655 ``default_category`` overrides the default category used for messages
656 when none is specified.
656 when none is specified.
657 """
657 """
658 self.session_key = session_key
658 self.session_key = session_key
659 if categories is not None:
659 if categories is not None:
660 self.categories = categories
660 self.categories = categories
661 if default_category is not None:
661 if default_category is not None:
662 self.default_category = default_category
662 self.default_category = default_category
663 if self.categories and self.default_category not in self.categories:
663 if self.categories and self.default_category not in self.categories:
664 raise ValueError(
664 raise ValueError(
665 "unrecognized default category %r" % (self.default_category,))
665 "unrecognized default category %r" % (self.default_category,))
666
666
667 def pop_messages(self, session=None, request=None):
667 def pop_messages(self, session=None, request=None):
668 """
668 """
669 Return all accumulated messages and delete them from the session.
669 Return all accumulated messages and delete them from the session.
670
670
671 The return value is a list of ``Message`` objects.
671 The return value is a list of ``Message`` objects.
672 """
672 """
673 messages = []
673 messages = []
674
674
675 if not session:
675 if not session:
676 if not request:
676 if not request:
677 request = get_current_request()
677 request = get_current_request()
678 session = request.session
678 session = request.session
679
679
680 # Pop the 'old' pylons flash messages. They are tuples of the form
680 # Pop the 'old' pylons flash messages. They are tuples of the form
681 # (category, message)
681 # (category, message)
682 for cat, msg in session.pop(self.session_key, []):
682 for cat, msg in session.pop(self.session_key, []):
683 messages.append(_Message(cat, msg))
683 messages.append(_Message(cat, msg))
684
684
685 # Pop the 'new' pyramid flash messages for each category as list
685 # Pop the 'new' pyramid flash messages for each category as list
686 # of strings.
686 # of strings.
687 for cat in self.categories:
687 for cat in self.categories:
688 for msg in session.pop_flash(queue=cat):
688 for msg in session.pop_flash(queue=cat):
689 messages.append(_Message(cat, msg))
689 messages.append(_Message(cat, msg))
690 # Map messages from the default queue to the 'notice' category.
690 # Map messages from the default queue to the 'notice' category.
691 for msg in session.pop_flash():
691 for msg in session.pop_flash():
692 messages.append(_Message('notice', msg))
692 messages.append(_Message('notice', msg))
693
693
694 session.save()
694 session.save()
695 return messages
695 return messages
696
696
697 def json_alerts(self, session=None, request=None):
697 def json_alerts(self, session=None, request=None):
698 payloads = []
698 payloads = []
699 messages = flash.pop_messages(session=session, request=request)
699 messages = flash.pop_messages(session=session, request=request)
700 if messages:
700 if messages:
701 for message in messages:
701 for message in messages:
702 subdata = {}
702 subdata = {}
703 if hasattr(message.message, 'rsplit'):
703 if hasattr(message.message, 'rsplit'):
704 flash_data = message.message.rsplit('|DELIM|', 1)
704 flash_data = message.message.rsplit('|DELIM|', 1)
705 org_message = flash_data[0]
705 org_message = flash_data[0]
706 if len(flash_data) > 1:
706 if len(flash_data) > 1:
707 subdata = json.loads(flash_data[1])
707 subdata = json.loads(flash_data[1])
708 else:
708 else:
709 org_message = message.message
709 org_message = message.message
710 payloads.append({
710 payloads.append({
711 'message': {
711 'message': {
712 'message': u'{}'.format(org_message),
712 'message': u'{}'.format(org_message),
713 'level': message.category,
713 'level': message.category,
714 'force': True,
714 'force': True,
715 'subdata': subdata
715 'subdata': subdata
716 }
716 }
717 })
717 })
718 return json.dumps(payloads)
718 return json.dumps(payloads)
719
719
720 def __call__(self, message, category=None, ignore_duplicate=False,
720 def __call__(self, message, category=None, ignore_duplicate=False,
721 session=None, request=None):
721 session=None, request=None):
722
722
723 if not session:
723 if not session:
724 if not request:
724 if not request:
725 request = get_current_request()
725 request = get_current_request()
726 session = request.session
726 session = request.session
727
727
728 session.flash(
728 session.flash(
729 message, queue=category, allow_duplicate=not ignore_duplicate)
729 message, queue=category, allow_duplicate=not ignore_duplicate)
730
730
731
731
732 flash = Flash()
732 flash = Flash()
733
733
734 #==============================================================================
734 #==============================================================================
735 # SCM FILTERS available via h.
735 # SCM FILTERS available via h.
736 #==============================================================================
736 #==============================================================================
737 from rhodecode.lib.vcs.utils import author_name, author_email
737 from rhodecode.lib.vcs.utils import author_name, author_email
738 from rhodecode.lib.utils2 import credentials_filter, age as _age
738 from rhodecode.lib.utils2 import credentials_filter, age as _age
739 from rhodecode.model.db import User, ChangesetStatus
739 from rhodecode.model.db import User, ChangesetStatus
740
740
741 age = _age
741 age = _age
742 capitalize = lambda x: x.capitalize()
742 capitalize = lambda x: x.capitalize()
743 email = author_email
743 email = author_email
744 short_id = lambda x: x[:12]
744 short_id = lambda x: x[:12]
745 hide_credentials = lambda x: ''.join(credentials_filter(x))
745 hide_credentials = lambda x: ''.join(credentials_filter(x))
746
746
747
747
748 import pytz
748 import pytz
749 import tzlocal
749 import tzlocal
750 local_timezone = tzlocal.get_localzone()
750 local_timezone = tzlocal.get_localzone()
751
751
752
752
753 def age_component(datetime_iso, value=None, time_is_local=False):
753 def age_component(datetime_iso, value=None, time_is_local=False):
754 title = value or format_date(datetime_iso)
754 title = value or format_date(datetime_iso)
755 tzinfo = '+00:00'
755 tzinfo = '+00:00'
756
756
757 # detect if we have a timezone info, otherwise, add it
757 # detect if we have a timezone info, otherwise, add it
758 if time_is_local and isinstance(datetime_iso, datetime) and not datetime_iso.tzinfo:
758 if time_is_local and isinstance(datetime_iso, datetime) and not datetime_iso.tzinfo:
759 force_timezone = os.environ.get('RC_TIMEZONE', '')
759 force_timezone = os.environ.get('RC_TIMEZONE', '')
760 if force_timezone:
760 if force_timezone:
761 force_timezone = pytz.timezone(force_timezone)
761 force_timezone = pytz.timezone(force_timezone)
762 timezone = force_timezone or local_timezone
762 timezone = force_timezone or local_timezone
763 offset = timezone.localize(datetime_iso).strftime('%z')
763 offset = timezone.localize(datetime_iso).strftime('%z')
764 tzinfo = '{}:{}'.format(offset[:-2], offset[-2:])
764 tzinfo = '{}:{}'.format(offset[:-2], offset[-2:])
765
765
766 return literal(
766 return literal(
767 '<time class="timeago tooltip" '
767 '<time class="timeago tooltip" '
768 'title="{1}{2}" datetime="{0}{2}">{1}</time>'.format(
768 'title="{1}{2}" datetime="{0}{2}">{1}</time>'.format(
769 datetime_iso, title, tzinfo))
769 datetime_iso, title, tzinfo))
770
770
771
771
772 def _shorten_commit_id(commit_id):
772 def _shorten_commit_id(commit_id):
773 from rhodecode import CONFIG
773 from rhodecode import CONFIG
774 def_len = safe_int(CONFIG.get('rhodecode_show_sha_length', 12))
774 def_len = safe_int(CONFIG.get('rhodecode_show_sha_length', 12))
775 return commit_id[:def_len]
775 return commit_id[:def_len]
776
776
777
777
778 def show_id(commit):
778 def show_id(commit):
779 """
779 """
780 Configurable function that shows ID
780 Configurable function that shows ID
781 by default it's r123:fffeeefffeee
781 by default it's r123:fffeeefffeee
782
782
783 :param commit: commit instance
783 :param commit: commit instance
784 """
784 """
785 from rhodecode import CONFIG
785 from rhodecode import CONFIG
786 show_idx = str2bool(CONFIG.get('rhodecode_show_revision_number', True))
786 show_idx = str2bool(CONFIG.get('rhodecode_show_revision_number', True))
787
787
788 raw_id = _shorten_commit_id(commit.raw_id)
788 raw_id = _shorten_commit_id(commit.raw_id)
789 if show_idx:
789 if show_idx:
790 return 'r%s:%s' % (commit.idx, raw_id)
790 return 'r%s:%s' % (commit.idx, raw_id)
791 else:
791 else:
792 return '%s' % (raw_id, )
792 return '%s' % (raw_id, )
793
793
794
794
795 def format_date(date):
795 def format_date(date):
796 """
796 """
797 use a standardized formatting for dates used in RhodeCode
797 use a standardized formatting for dates used in RhodeCode
798
798
799 :param date: date/datetime object
799 :param date: date/datetime object
800 :return: formatted date
800 :return: formatted date
801 """
801 """
802
802
803 if date:
803 if date:
804 _fmt = "%a, %d %b %Y %H:%M:%S"
804 _fmt = "%a, %d %b %Y %H:%M:%S"
805 return safe_unicode(date.strftime(_fmt))
805 return safe_unicode(date.strftime(_fmt))
806
806
807 return u""
807 return u""
808
808
809
809
810 class _RepoChecker(object):
810 class _RepoChecker(object):
811
811
812 def __init__(self, backend_alias):
812 def __init__(self, backend_alias):
813 self._backend_alias = backend_alias
813 self._backend_alias = backend_alias
814
814
815 def __call__(self, repository):
815 def __call__(self, repository):
816 if hasattr(repository, 'alias'):
816 if hasattr(repository, 'alias'):
817 _type = repository.alias
817 _type = repository.alias
818 elif hasattr(repository, 'repo_type'):
818 elif hasattr(repository, 'repo_type'):
819 _type = repository.repo_type
819 _type = repository.repo_type
820 else:
820 else:
821 _type = repository
821 _type = repository
822 return _type == self._backend_alias
822 return _type == self._backend_alias
823
823
824 is_git = _RepoChecker('git')
824 is_git = _RepoChecker('git')
825 is_hg = _RepoChecker('hg')
825 is_hg = _RepoChecker('hg')
826 is_svn = _RepoChecker('svn')
826 is_svn = _RepoChecker('svn')
827
827
828
828
829 def get_repo_type_by_name(repo_name):
829 def get_repo_type_by_name(repo_name):
830 repo = Repository.get_by_repo_name(repo_name)
830 repo = Repository.get_by_repo_name(repo_name)
831 return repo.repo_type
831 return repo.repo_type
832
832
833
833
834 def is_svn_without_proxy(repository):
834 def is_svn_without_proxy(repository):
835 if is_svn(repository):
835 if is_svn(repository):
836 from rhodecode.model.settings import VcsSettingsModel
836 from rhodecode.model.settings import VcsSettingsModel
837 conf = VcsSettingsModel().get_ui_settings_as_config_obj()
837 conf = VcsSettingsModel().get_ui_settings_as_config_obj()
838 return not str2bool(conf.get('vcs_svn_proxy', 'http_requests_enabled'))
838 return not str2bool(conf.get('vcs_svn_proxy', 'http_requests_enabled'))
839 return False
839 return False
840
840
841
841
842 def discover_user(author):
842 def discover_user(author):
843 """
843 """
844 Tries to discover RhodeCode User based on the autho string. Author string
844 Tries to discover RhodeCode User based on the autho string. Author string
845 is typically `FirstName LastName <email@address.com>`
845 is typically `FirstName LastName <email@address.com>`
846 """
846 """
847
847
848 # if author is already an instance use it for extraction
848 # if author is already an instance use it for extraction
849 if isinstance(author, User):
849 if isinstance(author, User):
850 return author
850 return author
851
851
852 # Valid email in the attribute passed, see if they're in the system
852 # Valid email in the attribute passed, see if they're in the system
853 _email = author_email(author)
853 _email = author_email(author)
854 if _email != '':
854 if _email != '':
855 user = User.get_by_email(_email, case_insensitive=True, cache=True)
855 user = User.get_by_email(_email, case_insensitive=True, cache=True)
856 if user is not None:
856 if user is not None:
857 return user
857 return user
858
858
859 # Maybe it's a username, we try to extract it and fetch by username ?
859 # Maybe it's a username, we try to extract it and fetch by username ?
860 _author = author_name(author)
860 _author = author_name(author)
861 user = User.get_by_username(_author, case_insensitive=True, cache=True)
861 user = User.get_by_username(_author, case_insensitive=True, cache=True)
862 if user is not None:
862 if user is not None:
863 return user
863 return user
864
864
865 return None
865 return None
866
866
867
867
868 def email_or_none(author):
868 def email_or_none(author):
869 # extract email from the commit string
869 # extract email from the commit string
870 _email = author_email(author)
870 _email = author_email(author)
871
871
872 # If we have an email, use it, otherwise
872 # If we have an email, use it, otherwise
873 # see if it contains a username we can get an email from
873 # see if it contains a username we can get an email from
874 if _email != '':
874 if _email != '':
875 return _email
875 return _email
876 else:
876 else:
877 user = User.get_by_username(
877 user = User.get_by_username(
878 author_name(author), case_insensitive=True, cache=True)
878 author_name(author), case_insensitive=True, cache=True)
879
879
880 if user is not None:
880 if user is not None:
881 return user.email
881 return user.email
882
882
883 # No valid email, not a valid user in the system, none!
883 # No valid email, not a valid user in the system, none!
884 return None
884 return None
885
885
886
886
887 def link_to_user(author, length=0, **kwargs):
887 def link_to_user(author, length=0, **kwargs):
888 user = discover_user(author)
888 user = discover_user(author)
889 # user can be None, but if we have it already it means we can re-use it
889 # user can be None, but if we have it already it means we can re-use it
890 # in the person() function, so we save 1 intensive-query
890 # in the person() function, so we save 1 intensive-query
891 if user:
891 if user:
892 author = user
892 author = user
893
893
894 display_person = person(author, 'username_or_name_or_email')
894 display_person = person(author, 'username_or_name_or_email')
895 if length:
895 if length:
896 display_person = shorter(display_person, length)
896 display_person = shorter(display_person, length)
897
897
898 if user:
898 if user:
899 return link_to(
899 return link_to(
900 escape(display_person),
900 escape(display_person),
901 route_path('user_profile', username=user.username),
901 route_path('user_profile', username=user.username),
902 **kwargs)
902 **kwargs)
903 else:
903 else:
904 return escape(display_person)
904 return escape(display_person)
905
905
906
906
907 def link_to_group(users_group_name, **kwargs):
907 def link_to_group(users_group_name, **kwargs):
908 return link_to(
908 return link_to(
909 escape(users_group_name),
909 escape(users_group_name),
910 route_path('user_group_profile', user_group_name=users_group_name),
910 route_path('user_group_profile', user_group_name=users_group_name),
911 **kwargs)
911 **kwargs)
912
912
913
913
914 def person(author, show_attr="username_and_name"):
914 def person(author, show_attr="username_and_name"):
915 user = discover_user(author)
915 user = discover_user(author)
916 if user:
916 if user:
917 return getattr(user, show_attr)
917 return getattr(user, show_attr)
918 else:
918 else:
919 _author = author_name(author)
919 _author = author_name(author)
920 _email = email(author)
920 _email = email(author)
921 return _author or _email
921 return _author or _email
922
922
923
923
924 def author_string(email):
924 def author_string(email):
925 if email:
925 if email:
926 user = User.get_by_email(email, case_insensitive=True, cache=True)
926 user = User.get_by_email(email, case_insensitive=True, cache=True)
927 if user:
927 if user:
928 if user.first_name or user.last_name:
928 if user.first_name or user.last_name:
929 return '%s %s &lt;%s&gt;' % (
929 return '%s %s &lt;%s&gt;' % (
930 user.first_name, user.last_name, email)
930 user.first_name, user.last_name, email)
931 else:
931 else:
932 return email
932 return email
933 else:
933 else:
934 return email
934 return email
935 else:
935 else:
936 return None
936 return None
937
937
938
938
939 def person_by_id(id_, show_attr="username_and_name"):
939 def person_by_id(id_, show_attr="username_and_name"):
940 # attr to return from fetched user
940 # attr to return from fetched user
941 person_getter = lambda usr: getattr(usr, show_attr)
941 person_getter = lambda usr: getattr(usr, show_attr)
942
942
943 #maybe it's an ID ?
943 #maybe it's an ID ?
944 if str(id_).isdigit() or isinstance(id_, int):
944 if str(id_).isdigit() or isinstance(id_, int):
945 id_ = int(id_)
945 id_ = int(id_)
946 user = User.get(id_)
946 user = User.get(id_)
947 if user is not None:
947 if user is not None:
948 return person_getter(user)
948 return person_getter(user)
949 return id_
949 return id_
950
950
951
951
952 def gravatar_with_user(request, author, show_disabled=False):
952 def gravatar_with_user(request, author, show_disabled=False):
953 _render = request.get_partial_renderer(
953 _render = request.get_partial_renderer(
954 'rhodecode:templates/base/base.mako')
954 'rhodecode:templates/base/base.mako')
955 return _render('gravatar_with_user', author, show_disabled=show_disabled)
955 return _render('gravatar_with_user', author, show_disabled=show_disabled)
956
956
957
957
958 tags_paterns = OrderedDict((
958 tags_paterns = OrderedDict((
959 ('lang', (re.compile(r'\[(lang|language)\ \=\&gt;\ *([a-zA-Z\-\/\#\+\.]*)\]'),
959 ('lang', (re.compile(r'\[(lang|language)\ \=\&gt;\ *([a-zA-Z\-\/\#\+\.]*)\]'),
960 '<div class="metatag" tag="lang">\\2</div>')),
960 '<div class="metatag" tag="lang">\\2</div>')),
961
961
962 ('see', (re.compile(r'\[see\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]'),
962 ('see', (re.compile(r'\[see\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]'),
963 '<div class="metatag" tag="see">see: \\1 </div>')),
963 '<div class="metatag" tag="see">see: \\1 </div>')),
964
964
965 ('url', (re.compile(r'\[url\ \=\&gt;\ \[([a-zA-Z0-9\ \.\-\_]+)\]\((http://|https://|/)(.*?)\)\]'),
965 ('url', (re.compile(r'\[url\ \=\&gt;\ \[([a-zA-Z0-9\ \.\-\_]+)\]\((http://|https://|/)(.*?)\)\]'),
966 '<div class="metatag" tag="url"> <a href="\\2\\3">\\1</a> </div>')),
966 '<div class="metatag" tag="url"> <a href="\\2\\3">\\1</a> </div>')),
967
967
968 ('license', (re.compile(r'\[license\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]'),
968 ('license', (re.compile(r'\[license\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]'),
969 '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/\\1">\\1</a></div>')),
969 '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/\\1">\\1</a></div>')),
970
970
971 ('ref', (re.compile(r'\[(requires|recommends|conflicts|base)\ \=\&gt;\ *([a-zA-Z0-9\-\/]*)\]'),
971 ('ref', (re.compile(r'\[(requires|recommends|conflicts|base)\ \=\&gt;\ *([a-zA-Z0-9\-\/]*)\]'),
972 '<div class="metatag" tag="ref \\1">\\1: <a href="/\\2">\\2</a></div>')),
972 '<div class="metatag" tag="ref \\1">\\1: <a href="/\\2">\\2</a></div>')),
973
973
974 ('state', (re.compile(r'\[(stable|featured|stale|dead|dev|deprecated)\]'),
974 ('state', (re.compile(r'\[(stable|featured|stale|dead|dev|deprecated)\]'),
975 '<div class="metatag" tag="state \\1">\\1</div>')),
975 '<div class="metatag" tag="state \\1">\\1</div>')),
976
976
977 # label in grey
977 # label in grey
978 ('label', (re.compile(r'\[([a-z]+)\]'),
978 ('label', (re.compile(r'\[([a-z]+)\]'),
979 '<div class="metatag" tag="label">\\1</div>')),
979 '<div class="metatag" tag="label">\\1</div>')),
980
980
981 # generic catch all in grey
981 # generic catch all in grey
982 ('generic', (re.compile(r'\[([a-zA-Z0-9\.\-\_]+)\]'),
982 ('generic', (re.compile(r'\[([a-zA-Z0-9\.\-\_]+)\]'),
983 '<div class="metatag" tag="generic">\\1</div>')),
983 '<div class="metatag" tag="generic">\\1</div>')),
984 ))
984 ))
985
985
986
986
987 def extract_metatags(value):
987 def extract_metatags(value):
988 """
988 """
989 Extract supported meta-tags from given text value
989 Extract supported meta-tags from given text value
990 """
990 """
991 tags = []
991 tags = []
992 if not value:
992 if not value:
993 return tags, ''
993 return tags, ''
994
994
995 for key, val in tags_paterns.items():
995 for key, val in tags_paterns.items():
996 pat, replace_html = val
996 pat, replace_html = val
997 tags.extend([(key, x.group()) for x in pat.finditer(value)])
997 tags.extend([(key, x.group()) for x in pat.finditer(value)])
998 value = pat.sub('', value)
998 value = pat.sub('', value)
999
999
1000 return tags, value
1000 return tags, value
1001
1001
1002
1002
1003 def style_metatag(tag_type, value):
1003 def style_metatag(tag_type, value):
1004 """
1004 """
1005 converts tags from value into html equivalent
1005 converts tags from value into html equivalent
1006 """
1006 """
1007 if not value:
1007 if not value:
1008 return ''
1008 return ''
1009
1009
1010 html_value = value
1010 html_value = value
1011 tag_data = tags_paterns.get(tag_type)
1011 tag_data = tags_paterns.get(tag_type)
1012 if tag_data:
1012 if tag_data:
1013 pat, replace_html = tag_data
1013 pat, replace_html = tag_data
1014 # convert to plain `unicode` instead of a markup tag to be used in
1014 # convert to plain `unicode` instead of a markup tag to be used in
1015 # regex expressions. safe_unicode doesn't work here
1015 # regex expressions. safe_unicode doesn't work here
1016 html_value = pat.sub(replace_html, unicode(value))
1016 html_value = pat.sub(replace_html, unicode(value))
1017
1017
1018 return html_value
1018 return html_value
1019
1019
1020
1020
1021 def bool2icon(value):
1021 def bool2icon(value):
1022 """
1022 """
1023 Returns boolean value of a given value, represented as html element with
1023 Returns boolean value of a given value, represented as html element with
1024 classes that will represent icons
1024 classes that will represent icons
1025
1025
1026 :param value: given value to convert to html node
1026 :param value: given value to convert to html node
1027 """
1027 """
1028
1028
1029 if value: # does bool conversion
1029 if value: # does bool conversion
1030 return HTML.tag('i', class_="icon-true")
1030 return HTML.tag('i', class_="icon-true")
1031 else: # not true as bool
1031 else: # not true as bool
1032 return HTML.tag('i', class_="icon-false")
1032 return HTML.tag('i', class_="icon-false")
1033
1033
1034
1034
1035 #==============================================================================
1035 #==============================================================================
1036 # PERMS
1036 # PERMS
1037 #==============================================================================
1037 #==============================================================================
1038 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
1038 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
1039 HasRepoPermissionAny, HasRepoPermissionAll, HasRepoGroupPermissionAll, \
1039 HasRepoPermissionAny, HasRepoPermissionAll, HasRepoGroupPermissionAll, \
1040 HasRepoGroupPermissionAny, HasRepoPermissionAnyApi, get_csrf_token, \
1040 HasRepoGroupPermissionAny, HasRepoPermissionAnyApi, get_csrf_token, \
1041 csrf_token_key
1041 csrf_token_key
1042
1042
1043
1043
1044 #==============================================================================
1044 #==============================================================================
1045 # GRAVATAR URL
1045 # GRAVATAR URL
1046 #==============================================================================
1046 #==============================================================================
1047 class InitialsGravatar(object):
1047 class InitialsGravatar(object):
1048 def __init__(self, email_address, first_name, last_name, size=30,
1048 def __init__(self, email_address, first_name, last_name, size=30,
1049 background=None, text_color='#fff'):
1049 background=None, text_color='#fff'):
1050 self.size = size
1050 self.size = size
1051 self.first_name = first_name
1051 self.first_name = first_name
1052 self.last_name = last_name
1052 self.last_name = last_name
1053 self.email_address = email_address
1053 self.email_address = email_address
1054 self.background = background or self.str2color(email_address)
1054 self.background = background or self.str2color(email_address)
1055 self.text_color = text_color
1055 self.text_color = text_color
1056
1056
1057 def get_color_bank(self):
1057 def get_color_bank(self):
1058 """
1058 """
1059 returns a predefined list of colors that gravatars can use.
1059 returns a predefined list of colors that gravatars can use.
1060 Those are randomized distinct colors that guarantee readability and
1060 Those are randomized distinct colors that guarantee readability and
1061 uniqueness.
1061 uniqueness.
1062
1062
1063 generated with: http://phrogz.net/css/distinct-colors.html
1063 generated with: http://phrogz.net/css/distinct-colors.html
1064 """
1064 """
1065 return [
1065 return [
1066 '#bf3030', '#a67f53', '#00ff00', '#5989b3', '#392040', '#d90000',
1066 '#bf3030', '#a67f53', '#00ff00', '#5989b3', '#392040', '#d90000',
1067 '#402910', '#204020', '#79baf2', '#a700b3', '#bf6060', '#7f5320',
1067 '#402910', '#204020', '#79baf2', '#a700b3', '#bf6060', '#7f5320',
1068 '#008000', '#003059', '#ee00ff', '#ff0000', '#8c4b00', '#007300',
1068 '#008000', '#003059', '#ee00ff', '#ff0000', '#8c4b00', '#007300',
1069 '#005fb3', '#de73e6', '#ff4040', '#ffaa00', '#3df255', '#203140',
1069 '#005fb3', '#de73e6', '#ff4040', '#ffaa00', '#3df255', '#203140',
1070 '#47004d', '#591616', '#664400', '#59b365', '#0d2133', '#83008c',
1070 '#47004d', '#591616', '#664400', '#59b365', '#0d2133', '#83008c',
1071 '#592d2d', '#bf9f60', '#73e682', '#1d3f73', '#73006b', '#402020',
1071 '#592d2d', '#bf9f60', '#73e682', '#1d3f73', '#73006b', '#402020',
1072 '#b2862d', '#397341', '#597db3', '#e600d6', '#a60000', '#736039',
1072 '#b2862d', '#397341', '#597db3', '#e600d6', '#a60000', '#736039',
1073 '#00b318', '#79aaf2', '#330d30', '#ff8080', '#403010', '#16591f',
1073 '#00b318', '#79aaf2', '#330d30', '#ff8080', '#403010', '#16591f',
1074 '#002459', '#8c4688', '#e50000', '#ffbf40', '#00732e', '#102340',
1074 '#002459', '#8c4688', '#e50000', '#ffbf40', '#00732e', '#102340',
1075 '#bf60ac', '#8c4646', '#cc8800', '#00a642', '#1d3473', '#b32d98',
1075 '#bf60ac', '#8c4646', '#cc8800', '#00a642', '#1d3473', '#b32d98',
1076 '#660e00', '#ffd580', '#80ffb2', '#7391e6', '#733967', '#d97b6c',
1076 '#660e00', '#ffd580', '#80ffb2', '#7391e6', '#733967', '#d97b6c',
1077 '#8c5e00', '#59b389', '#3967e6', '#590047', '#73281d', '#665200',
1077 '#8c5e00', '#59b389', '#3967e6', '#590047', '#73281d', '#665200',
1078 '#00e67a', '#2d50b3', '#8c2377', '#734139', '#b2982d', '#16593a',
1078 '#00e67a', '#2d50b3', '#8c2377', '#734139', '#b2982d', '#16593a',
1079 '#001859', '#ff00aa', '#a65e53', '#ffcc00', '#0d3321', '#2d3959',
1079 '#001859', '#ff00aa', '#a65e53', '#ffcc00', '#0d3321', '#2d3959',
1080 '#731d56', '#401610', '#4c3d00', '#468c6c', '#002ca6', '#d936a3',
1080 '#731d56', '#401610', '#4c3d00', '#468c6c', '#002ca6', '#d936a3',
1081 '#d94c36', '#403920', '#36d9a3', '#0d1733', '#592d4a', '#993626',
1081 '#d94c36', '#403920', '#36d9a3', '#0d1733', '#592d4a', '#993626',
1082 '#cca300', '#00734d', '#46598c', '#8c005e', '#7f1100', '#8c7000',
1082 '#cca300', '#00734d', '#46598c', '#8c005e', '#7f1100', '#8c7000',
1083 '#00a66f', '#7382e6', '#b32d74', '#d9896c', '#ffe680', '#1d7362',
1083 '#00a66f', '#7382e6', '#b32d74', '#d9896c', '#ffe680', '#1d7362',
1084 '#364cd9', '#73003d', '#d93a00', '#998a4d', '#59b3a1', '#5965b3',
1084 '#364cd9', '#73003d', '#d93a00', '#998a4d', '#59b3a1', '#5965b3',
1085 '#e5007a', '#73341d', '#665f00', '#00b38f', '#0018b3', '#59163a',
1085 '#e5007a', '#73341d', '#665f00', '#00b38f', '#0018b3', '#59163a',
1086 '#b2502d', '#bfb960', '#00ffcc', '#23318c', '#a6537f', '#734939',
1086 '#b2502d', '#bfb960', '#00ffcc', '#23318c', '#a6537f', '#734939',
1087 '#b2a700', '#104036', '#3d3df2', '#402031', '#e56739', '#736f39',
1087 '#b2a700', '#104036', '#3d3df2', '#402031', '#e56739', '#736f39',
1088 '#79f2ea', '#000059', '#401029', '#4c1400', '#ffee00', '#005953',
1088 '#79f2ea', '#000059', '#401029', '#4c1400', '#ffee00', '#005953',
1089 '#101040', '#990052', '#402820', '#403d10', '#00ffee', '#0000d9',
1089 '#101040', '#990052', '#402820', '#403d10', '#00ffee', '#0000d9',
1090 '#ff80c4', '#a66953', '#eeff00', '#00ccbe', '#8080ff', '#e673a1',
1090 '#ff80c4', '#a66953', '#eeff00', '#00ccbe', '#8080ff', '#e673a1',
1091 '#a62c00', '#474d00', '#1a3331', '#46468c', '#733950', '#662900',
1091 '#a62c00', '#474d00', '#1a3331', '#46468c', '#733950', '#662900',
1092 '#858c23', '#238c85', '#0f0073', '#b20047', '#d9986c', '#becc00',
1092 '#858c23', '#238c85', '#0f0073', '#b20047', '#d9986c', '#becc00',
1093 '#396f73', '#281d73', '#ff0066', '#ff6600', '#dee673', '#59adb3',
1093 '#396f73', '#281d73', '#ff0066', '#ff6600', '#dee673', '#59adb3',
1094 '#6559b3', '#590024', '#b2622d', '#98b32d', '#36ced9', '#332d59',
1094 '#6559b3', '#590024', '#b2622d', '#98b32d', '#36ced9', '#332d59',
1095 '#40001a', '#733f1d', '#526600', '#005359', '#242040', '#bf6079',
1095 '#40001a', '#733f1d', '#526600', '#005359', '#242040', '#bf6079',
1096 '#735039', '#cef23d', '#007780', '#5630bf', '#66001b', '#b24700',
1096 '#735039', '#cef23d', '#007780', '#5630bf', '#66001b', '#b24700',
1097 '#acbf60', '#1d6273', '#25008c', '#731d34', '#a67453', '#50592d',
1097 '#acbf60', '#1d6273', '#25008c', '#731d34', '#a67453', '#50592d',
1098 '#00ccff', '#6600ff', '#ff0044', '#4c1f00', '#8a994d', '#79daf2',
1098 '#00ccff', '#6600ff', '#ff0044', '#4c1f00', '#8a994d', '#79daf2',
1099 '#a173e6', '#d93662', '#402310', '#aaff00', '#2d98b3', '#8c40ff',
1099 '#a173e6', '#d93662', '#402310', '#aaff00', '#2d98b3', '#8c40ff',
1100 '#592d39', '#ff8c40', '#354020', '#103640', '#1a0040', '#331a20',
1100 '#592d39', '#ff8c40', '#354020', '#103640', '#1a0040', '#331a20',
1101 '#331400', '#334d00', '#1d5673', '#583973', '#7f0022', '#4c3626',
1101 '#331400', '#334d00', '#1d5673', '#583973', '#7f0022', '#4c3626',
1102 '#88cc00', '#36a3d9', '#3d0073', '#d9364c', '#33241a', '#698c23',
1102 '#88cc00', '#36a3d9', '#3d0073', '#d9364c', '#33241a', '#698c23',
1103 '#5995b3', '#300059', '#e57382', '#7f3300', '#366600', '#00aaff',
1103 '#5995b3', '#300059', '#e57382', '#7f3300', '#366600', '#00aaff',
1104 '#3a1659', '#733941', '#663600', '#74b32d', '#003c59', '#7f53a6',
1104 '#3a1659', '#733941', '#663600', '#74b32d', '#003c59', '#7f53a6',
1105 '#73000f', '#ff8800', '#baf279', '#79caf2', '#291040', '#a6293a',
1105 '#73000f', '#ff8800', '#baf279', '#79caf2', '#291040', '#a6293a',
1106 '#b2742d', '#587339', '#0077b3', '#632699', '#400009', '#d9a66c',
1106 '#b2742d', '#587339', '#0077b3', '#632699', '#400009', '#d9a66c',
1107 '#294010', '#2d4a59', '#aa00ff', '#4c131b', '#b25f00', '#5ce600',
1107 '#294010', '#2d4a59', '#aa00ff', '#4c131b', '#b25f00', '#5ce600',
1108 '#267399', '#a336d9', '#990014', '#664e33', '#86bf60', '#0088ff',
1108 '#267399', '#a336d9', '#990014', '#664e33', '#86bf60', '#0088ff',
1109 '#7700b3', '#593a16', '#073300', '#1d4b73', '#ac60bf', '#e59539',
1109 '#7700b3', '#593a16', '#073300', '#1d4b73', '#ac60bf', '#e59539',
1110 '#4f8c46', '#368dd9', '#5c0073'
1110 '#4f8c46', '#368dd9', '#5c0073'
1111 ]
1111 ]
1112
1112
1113 def rgb_to_hex_color(self, rgb_tuple):
1113 def rgb_to_hex_color(self, rgb_tuple):
1114 """
1114 """
1115 Converts an rgb_tuple passed to an hex color.
1115 Converts an rgb_tuple passed to an hex color.
1116
1116
1117 :param rgb_tuple: tuple with 3 ints represents rgb color space
1117 :param rgb_tuple: tuple with 3 ints represents rgb color space
1118 """
1118 """
1119 return '#' + ("".join(map(chr, rgb_tuple)).encode('hex'))
1119 return '#' + ("".join(map(chr, rgb_tuple)).encode('hex'))
1120
1120
1121 def email_to_int_list(self, email_str):
1121 def email_to_int_list(self, email_str):
1122 """
1122 """
1123 Get every byte of the hex digest value of email and turn it to integer.
1123 Get every byte of the hex digest value of email and turn it to integer.
1124 It's going to be always between 0-255
1124 It's going to be always between 0-255
1125 """
1125 """
1126 digest = md5_safe(email_str.lower())
1126 digest = md5_safe(email_str.lower())
1127 return [int(digest[i * 2:i * 2 + 2], 16) for i in range(16)]
1127 return [int(digest[i * 2:i * 2 + 2], 16) for i in range(16)]
1128
1128
1129 def pick_color_bank_index(self, email_str, color_bank):
1129 def pick_color_bank_index(self, email_str, color_bank):
1130 return self.email_to_int_list(email_str)[0] % len(color_bank)
1130 return self.email_to_int_list(email_str)[0] % len(color_bank)
1131
1131
1132 def str2color(self, email_str):
1132 def str2color(self, email_str):
1133 """
1133 """
1134 Tries to map in a stable algorithm an email to color
1134 Tries to map in a stable algorithm an email to color
1135
1135
1136 :param email_str:
1136 :param email_str:
1137 """
1137 """
1138 color_bank = self.get_color_bank()
1138 color_bank = self.get_color_bank()
1139 # pick position (module it's length so we always find it in the
1139 # pick position (module it's length so we always find it in the
1140 # bank even if it's smaller than 256 values
1140 # bank even if it's smaller than 256 values
1141 pos = self.pick_color_bank_index(email_str, color_bank)
1141 pos = self.pick_color_bank_index(email_str, color_bank)
1142 return color_bank[pos]
1142 return color_bank[pos]
1143
1143
1144 def normalize_email(self, email_address):
1144 def normalize_email(self, email_address):
1145 import unicodedata
1145 import unicodedata
1146 # default host used to fill in the fake/missing email
1146 # default host used to fill in the fake/missing email
1147 default_host = u'localhost'
1147 default_host = u'localhost'
1148
1148
1149 if not email_address:
1149 if not email_address:
1150 email_address = u'%s@%s' % (User.DEFAULT_USER, default_host)
1150 email_address = u'%s@%s' % (User.DEFAULT_USER, default_host)
1151
1151
1152 email_address = safe_unicode(email_address)
1152 email_address = safe_unicode(email_address)
1153
1153
1154 if u'@' not in email_address:
1154 if u'@' not in email_address:
1155 email_address = u'%s@%s' % (email_address, default_host)
1155 email_address = u'%s@%s' % (email_address, default_host)
1156
1156
1157 if email_address.endswith(u'@'):
1157 if email_address.endswith(u'@'):
1158 email_address = u'%s%s' % (email_address, default_host)
1158 email_address = u'%s%s' % (email_address, default_host)
1159
1159
1160 email_address = unicodedata.normalize('NFKD', email_address)\
1160 email_address = unicodedata.normalize('NFKD', email_address)\
1161 .encode('ascii', 'ignore')
1161 .encode('ascii', 'ignore')
1162 return email_address
1162 return email_address
1163
1163
1164 def get_initials(self):
1164 def get_initials(self):
1165 """
1165 """
1166 Returns 2 letter initials calculated based on the input.
1166 Returns 2 letter initials calculated based on the input.
1167 The algorithm picks first given email address, and takes first letter
1167 The algorithm picks first given email address, and takes first letter
1168 of part before @, and then the first letter of server name. In case
1168 of part before @, and then the first letter of server name. In case
1169 the part before @ is in a format of `somestring.somestring2` it replaces
1169 the part before @ is in a format of `somestring.somestring2` it replaces
1170 the server letter with first letter of somestring2
1170 the server letter with first letter of somestring2
1171
1171
1172 In case function was initialized with both first and lastname, this
1172 In case function was initialized with both first and lastname, this
1173 overrides the extraction from email by first letter of the first and
1173 overrides the extraction from email by first letter of the first and
1174 last name. We add special logic to that functionality, In case Full name
1174 last name. We add special logic to that functionality, In case Full name
1175 is compound, like Guido Von Rossum, we use last part of the last name
1175 is compound, like Guido Von Rossum, we use last part of the last name
1176 (Von Rossum) picking `R`.
1176 (Von Rossum) picking `R`.
1177
1177
1178 Function also normalizes the non-ascii characters to they ascii
1178 Function also normalizes the non-ascii characters to they ascii
1179 representation, eg Ą => A
1179 representation, eg Ą => A
1180 """
1180 """
1181 import unicodedata
1181 import unicodedata
1182 # replace non-ascii to ascii
1182 # replace non-ascii to ascii
1183 first_name = unicodedata.normalize(
1183 first_name = unicodedata.normalize(
1184 'NFKD', safe_unicode(self.first_name)).encode('ascii', 'ignore')
1184 'NFKD', safe_unicode(self.first_name)).encode('ascii', 'ignore')
1185 last_name = unicodedata.normalize(
1185 last_name = unicodedata.normalize(
1186 'NFKD', safe_unicode(self.last_name)).encode('ascii', 'ignore')
1186 'NFKD', safe_unicode(self.last_name)).encode('ascii', 'ignore')
1187
1187
1188 # do NFKD encoding, and also make sure email has proper format
1188 # do NFKD encoding, and also make sure email has proper format
1189 email_address = self.normalize_email(self.email_address)
1189 email_address = self.normalize_email(self.email_address)
1190
1190
1191 # first push the email initials
1191 # first push the email initials
1192 prefix, server = email_address.split('@', 1)
1192 prefix, server = email_address.split('@', 1)
1193
1193
1194 # check if prefix is maybe a 'first_name.last_name' syntax
1194 # check if prefix is maybe a 'first_name.last_name' syntax
1195 _dot_split = prefix.rsplit('.', 1)
1195 _dot_split = prefix.rsplit('.', 1)
1196 if len(_dot_split) == 2 and _dot_split[1]:
1196 if len(_dot_split) == 2 and _dot_split[1]:
1197 initials = [_dot_split[0][0], _dot_split[1][0]]
1197 initials = [_dot_split[0][0], _dot_split[1][0]]
1198 else:
1198 else:
1199 initials = [prefix[0], server[0]]
1199 initials = [prefix[0], server[0]]
1200
1200
1201 # then try to replace either first_name or last_name
1201 # then try to replace either first_name or last_name
1202 fn_letter = (first_name or " ")[0].strip()
1202 fn_letter = (first_name or " ")[0].strip()
1203 ln_letter = (last_name.split(' ', 1)[-1] or " ")[0].strip()
1203 ln_letter = (last_name.split(' ', 1)[-1] or " ")[0].strip()
1204
1204
1205 if fn_letter:
1205 if fn_letter:
1206 initials[0] = fn_letter
1206 initials[0] = fn_letter
1207
1207
1208 if ln_letter:
1208 if ln_letter:
1209 initials[1] = ln_letter
1209 initials[1] = ln_letter
1210
1210
1211 return ''.join(initials).upper()
1211 return ''.join(initials).upper()
1212
1212
1213 def get_img_data_by_type(self, font_family, img_type):
1213 def get_img_data_by_type(self, font_family, img_type):
1214 default_user = """
1214 default_user = """
1215 <svg xmlns="http://www.w3.org/2000/svg"
1215 <svg xmlns="http://www.w3.org/2000/svg"
1216 version="1.1" x="0px" y="0px" width="{size}" height="{size}"
1216 version="1.1" x="0px" y="0px" width="{size}" height="{size}"
1217 viewBox="-15 -10 439.165 429.164"
1217 viewBox="-15 -10 439.165 429.164"
1218
1218
1219 xml:space="preserve"
1219 xml:space="preserve"
1220 style="background:{background};" >
1220 style="background:{background};" >
1221
1221
1222 <path d="M204.583,216.671c50.664,0,91.74-48.075,
1222 <path d="M204.583,216.671c50.664,0,91.74-48.075,
1223 91.74-107.378c0-82.237-41.074-107.377-91.74-107.377
1223 91.74-107.378c0-82.237-41.074-107.377-91.74-107.377
1224 c-50.668,0-91.74,25.14-91.74,107.377C112.844,
1224 c-50.668,0-91.74,25.14-91.74,107.377C112.844,
1225 168.596,153.916,216.671,
1225 168.596,153.916,216.671,
1226 204.583,216.671z" fill="{text_color}"/>
1226 204.583,216.671z" fill="{text_color}"/>
1227 <path d="M407.164,374.717L360.88,
1227 <path d="M407.164,374.717L360.88,
1228 270.454c-2.117-4.771-5.836-8.728-10.465-11.138l-71.83-37.392
1228 270.454c-2.117-4.771-5.836-8.728-10.465-11.138l-71.83-37.392
1229 c-1.584-0.823-3.502-0.663-4.926,0.415c-20.316,
1229 c-1.584-0.823-3.502-0.663-4.926,0.415c-20.316,
1230 15.366-44.203,23.488-69.076,23.488c-24.877,
1230 15.366-44.203,23.488-69.076,23.488c-24.877,
1231 0-48.762-8.122-69.078-23.488
1231 0-48.762-8.122-69.078-23.488
1232 c-1.428-1.078-3.346-1.238-4.93-0.415L58.75,
1232 c-1.428-1.078-3.346-1.238-4.93-0.415L58.75,
1233 259.316c-4.631,2.41-8.346,6.365-10.465,11.138L2.001,374.717
1233 259.316c-4.631,2.41-8.346,6.365-10.465,11.138L2.001,374.717
1234 c-3.191,7.188-2.537,15.412,1.75,22.005c4.285,
1234 c-3.191,7.188-2.537,15.412,1.75,22.005c4.285,
1235 6.592,11.537,10.526,19.4,10.526h362.861c7.863,0,15.117-3.936,
1235 6.592,11.537,10.526,19.4,10.526h362.861c7.863,0,15.117-3.936,
1236 19.402-10.527 C409.699,390.129,
1236 19.402-10.527 C409.699,390.129,
1237 410.355,381.902,407.164,374.717z" fill="{text_color}"/>
1237 410.355,381.902,407.164,374.717z" fill="{text_color}"/>
1238 </svg>""".format(
1238 </svg>""".format(
1239 size=self.size,
1239 size=self.size,
1240 background='#979797', # @grey4
1240 background='#979797', # @grey4
1241 text_color=self.text_color,
1241 text_color=self.text_color,
1242 font_family=font_family)
1242 font_family=font_family)
1243
1243
1244 return {
1244 return {
1245 "default_user": default_user
1245 "default_user": default_user
1246 }[img_type]
1246 }[img_type]
1247
1247
1248 def get_img_data(self, svg_type=None):
1248 def get_img_data(self, svg_type=None):
1249 """
1249 """
1250 generates the svg metadata for image
1250 generates the svg metadata for image
1251 """
1251 """
1252
1252 fonts = [
1253 font_family = ','.join([
1253 '-apple-system',
1254 'proximanovaregular',
1254 'BlinkMacSystemFont',
1255 'Proxima Nova Regular',
1255 'Segoe UI',
1256 'Proxima Nova',
1256 'Roboto',
1257 'Arial',
1257 'Oxygen-Sans',
1258 'Lucida Grande',
1258 'Ubuntu',
1259 'Cantarell',
1260 'Helvetica Neue',
1259 'sans-serif'
1261 'sans-serif'
1260 ])
1262 ]
1263 font_family = ','.join(fonts)
1261 if svg_type:
1264 if svg_type:
1262 return self.get_img_data_by_type(font_family, svg_type)
1265 return self.get_img_data_by_type(font_family, svg_type)
1263
1266
1264 initials = self.get_initials()
1267 initials = self.get_initials()
1265 img_data = """
1268 img_data = """
1266 <svg xmlns="http://www.w3.org/2000/svg" pointer-events="none"
1269 <svg xmlns="http://www.w3.org/2000/svg" pointer-events="none"
1267 width="{size}" height="{size}"
1270 width="{size}" height="{size}"
1268 style="width: 100%; height: 100%; background-color: {background}"
1271 style="width: 100%; height: 100%; background-color: {background}"
1269 viewBox="0 0 {size} {size}">
1272 viewBox="0 0 {size} {size}">
1270 <text text-anchor="middle" y="50%" x="50%" dy="0.35em"
1273 <text text-anchor="middle" y="50%" x="50%" dy="0.35em"
1271 pointer-events="auto" fill="{text_color}"
1274 pointer-events="auto" fill="{text_color}"
1272 font-family="{font_family}"
1275 font-family="{font_family}"
1273 style="font-weight: 400; font-size: {f_size}px;">{text}
1276 style="font-weight: 400; font-size: {f_size}px;">{text}
1274 </text>
1277 </text>
1275 </svg>""".format(
1278 </svg>""".format(
1276 size=self.size,
1279 size=self.size,
1277 f_size=self.size/1.85, # scale the text inside the box nicely
1280 f_size=self.size/1.85, # scale the text inside the box nicely
1278 background=self.background,
1281 background=self.background,
1279 text_color=self.text_color,
1282 text_color=self.text_color,
1280 text=initials.upper(),
1283 text=initials.upper(),
1281 font_family=font_family)
1284 font_family=font_family)
1282
1285
1283 return img_data
1286 return img_data
1284
1287
1285 def generate_svg(self, svg_type=None):
1288 def generate_svg(self, svg_type=None):
1286 img_data = self.get_img_data(svg_type)
1289 img_data = self.get_img_data(svg_type)
1287 return "data:image/svg+xml;base64,%s" % img_data.encode('base64')
1290 return "data:image/svg+xml;base64,%s" % img_data.encode('base64')
1288
1291
1289
1292
1290 def initials_gravatar(email_address, first_name, last_name, size=30):
1293 def initials_gravatar(email_address, first_name, last_name, size=30):
1291 svg_type = None
1294 svg_type = None
1292 if email_address == User.DEFAULT_USER_EMAIL:
1295 if email_address == User.DEFAULT_USER_EMAIL:
1293 svg_type = 'default_user'
1296 svg_type = 'default_user'
1294 klass = InitialsGravatar(email_address, first_name, last_name, size)
1297 klass = InitialsGravatar(email_address, first_name, last_name, size)
1295 return klass.generate_svg(svg_type=svg_type)
1298 return klass.generate_svg(svg_type=svg_type)
1296
1299
1297
1300
1298 def gravatar_url(email_address, size=30, request=None):
1301 def gravatar_url(email_address, size=30, request=None):
1299 request = get_current_request()
1302 request = get_current_request()
1300 _use_gravatar = request.call_context.visual.use_gravatar
1303 _use_gravatar = request.call_context.visual.use_gravatar
1301 _gravatar_url = request.call_context.visual.gravatar_url
1304 _gravatar_url = request.call_context.visual.gravatar_url
1302
1305
1303 _gravatar_url = _gravatar_url or User.DEFAULT_GRAVATAR_URL
1306 _gravatar_url = _gravatar_url or User.DEFAULT_GRAVATAR_URL
1304
1307
1305 email_address = email_address or User.DEFAULT_USER_EMAIL
1308 email_address = email_address or User.DEFAULT_USER_EMAIL
1306 if isinstance(email_address, unicode):
1309 if isinstance(email_address, unicode):
1307 # hashlib crashes on unicode items
1310 # hashlib crashes on unicode items
1308 email_address = safe_str(email_address)
1311 email_address = safe_str(email_address)
1309
1312
1310 # empty email or default user
1313 # empty email or default user
1311 if not email_address or email_address == User.DEFAULT_USER_EMAIL:
1314 if not email_address or email_address == User.DEFAULT_USER_EMAIL:
1312 return initials_gravatar(User.DEFAULT_USER_EMAIL, '', '', size=size)
1315 return initials_gravatar(User.DEFAULT_USER_EMAIL, '', '', size=size)
1313
1316
1314 if _use_gravatar:
1317 if _use_gravatar:
1315 # TODO: Disuse pyramid thread locals. Think about another solution to
1318 # TODO: Disuse pyramid thread locals. Think about another solution to
1316 # get the host and schema here.
1319 # get the host and schema here.
1317 request = get_current_request()
1320 request = get_current_request()
1318 tmpl = safe_str(_gravatar_url)
1321 tmpl = safe_str(_gravatar_url)
1319 tmpl = tmpl.replace('{email}', email_address)\
1322 tmpl = tmpl.replace('{email}', email_address)\
1320 .replace('{md5email}', md5_safe(email_address.lower())) \
1323 .replace('{md5email}', md5_safe(email_address.lower())) \
1321 .replace('{netloc}', request.host)\
1324 .replace('{netloc}', request.host)\
1322 .replace('{scheme}', request.scheme)\
1325 .replace('{scheme}', request.scheme)\
1323 .replace('{size}', safe_str(size))
1326 .replace('{size}', safe_str(size))
1324 return tmpl
1327 return tmpl
1325 else:
1328 else:
1326 return initials_gravatar(email_address, '', '', size=size)
1329 return initials_gravatar(email_address, '', '', size=size)
1327
1330
1328
1331
1329 class Page(_Page):
1332 class Page(_Page):
1330 """
1333 """
1331 Custom pager to match rendering style with paginator
1334 Custom pager to match rendering style with paginator
1332 """
1335 """
1333
1336
1334 def _get_pos(self, cur_page, max_page, items):
1337 def _get_pos(self, cur_page, max_page, items):
1335 edge = (items / 2) + 1
1338 edge = (items / 2) + 1
1336 if (cur_page <= edge):
1339 if (cur_page <= edge):
1337 radius = max(items / 2, items - cur_page)
1340 radius = max(items / 2, items - cur_page)
1338 elif (max_page - cur_page) < edge:
1341 elif (max_page - cur_page) < edge:
1339 radius = (items - 1) - (max_page - cur_page)
1342 radius = (items - 1) - (max_page - cur_page)
1340 else:
1343 else:
1341 radius = items / 2
1344 radius = items / 2
1342
1345
1343 left = max(1, (cur_page - (radius)))
1346 left = max(1, (cur_page - (radius)))
1344 right = min(max_page, cur_page + (radius))
1347 right = min(max_page, cur_page + (radius))
1345 return left, cur_page, right
1348 return left, cur_page, right
1346
1349
1347 def _range(self, regexp_match):
1350 def _range(self, regexp_match):
1348 """
1351 """
1349 Return range of linked pages (e.g. '1 2 [3] 4 5 6 7 8').
1352 Return range of linked pages (e.g. '1 2 [3] 4 5 6 7 8').
1350
1353
1351 Arguments:
1354 Arguments:
1352
1355
1353 regexp_match
1356 regexp_match
1354 A "re" (regular expressions) match object containing the
1357 A "re" (regular expressions) match object containing the
1355 radius of linked pages around the current page in
1358 radius of linked pages around the current page in
1356 regexp_match.group(1) as a string
1359 regexp_match.group(1) as a string
1357
1360
1358 This function is supposed to be called as a callable in
1361 This function is supposed to be called as a callable in
1359 re.sub.
1362 re.sub.
1360
1363
1361 """
1364 """
1362 radius = int(regexp_match.group(1))
1365 radius = int(regexp_match.group(1))
1363
1366
1364 # Compute the first and last page number within the radius
1367 # Compute the first and last page number within the radius
1365 # e.g. '1 .. 5 6 [7] 8 9 .. 12'
1368 # e.g. '1 .. 5 6 [7] 8 9 .. 12'
1366 # -> leftmost_page = 5
1369 # -> leftmost_page = 5
1367 # -> rightmost_page = 9
1370 # -> rightmost_page = 9
1368 leftmost_page, _cur, rightmost_page = self._get_pos(self.page,
1371 leftmost_page, _cur, rightmost_page = self._get_pos(self.page,
1369 self.last_page,
1372 self.last_page,
1370 (radius * 2) + 1)
1373 (radius * 2) + 1)
1371 nav_items = []
1374 nav_items = []
1372
1375
1373 # Create a link to the first page (unless we are on the first page
1376 # Create a link to the first page (unless we are on the first page
1374 # or there would be no need to insert '..' spacers)
1377 # or there would be no need to insert '..' spacers)
1375 if self.page != self.first_page and self.first_page < leftmost_page:
1378 if self.page != self.first_page and self.first_page < leftmost_page:
1376 nav_items.append(self._pagerlink(self.first_page, self.first_page))
1379 nav_items.append(self._pagerlink(self.first_page, self.first_page))
1377
1380
1378 # Insert dots if there are pages between the first page
1381 # Insert dots if there are pages between the first page
1379 # and the currently displayed page range
1382 # and the currently displayed page range
1380 if leftmost_page - self.first_page > 1:
1383 if leftmost_page - self.first_page > 1:
1381 # Wrap in a SPAN tag if nolink_attr is set
1384 # Wrap in a SPAN tag if nolink_attr is set
1382 text = '..'
1385 text = '..'
1383 if self.dotdot_attr:
1386 if self.dotdot_attr:
1384 text = HTML.span(c=text, **self.dotdot_attr)
1387 text = HTML.span(c=text, **self.dotdot_attr)
1385 nav_items.append(text)
1388 nav_items.append(text)
1386
1389
1387 for thispage in xrange(leftmost_page, rightmost_page + 1):
1390 for thispage in xrange(leftmost_page, rightmost_page + 1):
1388 # Hilight the current page number and do not use a link
1391 # Hilight the current page number and do not use a link
1389 if thispage == self.page:
1392 if thispage == self.page:
1390 text = '%s' % (thispage,)
1393 text = '%s' % (thispage,)
1391 # Wrap in a SPAN tag if nolink_attr is set
1394 # Wrap in a SPAN tag if nolink_attr is set
1392 if self.curpage_attr:
1395 if self.curpage_attr:
1393 text = HTML.span(c=text, **self.curpage_attr)
1396 text = HTML.span(c=text, **self.curpage_attr)
1394 nav_items.append(text)
1397 nav_items.append(text)
1395 # Otherwise create just a link to that page
1398 # Otherwise create just a link to that page
1396 else:
1399 else:
1397 text = '%s' % (thispage,)
1400 text = '%s' % (thispage,)
1398 nav_items.append(self._pagerlink(thispage, text))
1401 nav_items.append(self._pagerlink(thispage, text))
1399
1402
1400 # Insert dots if there are pages between the displayed
1403 # Insert dots if there are pages between the displayed
1401 # page numbers and the end of the page range
1404 # page numbers and the end of the page range
1402 if self.last_page - rightmost_page > 1:
1405 if self.last_page - rightmost_page > 1:
1403 text = '..'
1406 text = '..'
1404 # Wrap in a SPAN tag if nolink_attr is set
1407 # Wrap in a SPAN tag if nolink_attr is set
1405 if self.dotdot_attr:
1408 if self.dotdot_attr:
1406 text = HTML.span(c=text, **self.dotdot_attr)
1409 text = HTML.span(c=text, **self.dotdot_attr)
1407 nav_items.append(text)
1410 nav_items.append(text)
1408
1411
1409 # Create a link to the very last page (unless we are on the last
1412 # Create a link to the very last page (unless we are on the last
1410 # page or there would be no need to insert '..' spacers)
1413 # page or there would be no need to insert '..' spacers)
1411 if self.page != self.last_page and rightmost_page < self.last_page:
1414 if self.page != self.last_page and rightmost_page < self.last_page:
1412 nav_items.append(self._pagerlink(self.last_page, self.last_page))
1415 nav_items.append(self._pagerlink(self.last_page, self.last_page))
1413
1416
1414 ## prerender links
1417 ## prerender links
1415 #_page_link = url.current()
1418 #_page_link = url.current()
1416 #nav_items.append(literal('<link rel="prerender" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
1419 #nav_items.append(literal('<link rel="prerender" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
1417 #nav_items.append(literal('<link rel="prefetch" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
1420 #nav_items.append(literal('<link rel="prefetch" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
1418 return self.separator.join(nav_items)
1421 return self.separator.join(nav_items)
1419
1422
1420 def pager(self, format='~2~', page_param='page', partial_param='partial',
1423 def pager(self, format='~2~', page_param='page', partial_param='partial',
1421 show_if_single_page=False, separator=' ', onclick=None,
1424 show_if_single_page=False, separator=' ', onclick=None,
1422 symbol_first='<<', symbol_last='>>',
1425 symbol_first='<<', symbol_last='>>',
1423 symbol_previous='<', symbol_next='>',
1426 symbol_previous='<', symbol_next='>',
1424 link_attr={'class': 'pager_link', 'rel': 'prerender'},
1427 link_attr={'class': 'pager_link', 'rel': 'prerender'},
1425 curpage_attr={'class': 'pager_curpage'},
1428 curpage_attr={'class': 'pager_curpage'},
1426 dotdot_attr={'class': 'pager_dotdot'}, **kwargs):
1429 dotdot_attr={'class': 'pager_dotdot'}, **kwargs):
1427
1430
1428 self.curpage_attr = curpage_attr
1431 self.curpage_attr = curpage_attr
1429 self.separator = separator
1432 self.separator = separator
1430 self.pager_kwargs = kwargs
1433 self.pager_kwargs = kwargs
1431 self.page_param = page_param
1434 self.page_param = page_param
1432 self.partial_param = partial_param
1435 self.partial_param = partial_param
1433 self.onclick = onclick
1436 self.onclick = onclick
1434 self.link_attr = link_attr
1437 self.link_attr = link_attr
1435 self.dotdot_attr = dotdot_attr
1438 self.dotdot_attr = dotdot_attr
1436
1439
1437 # Don't show navigator if there is no more than one page
1440 # Don't show navigator if there is no more than one page
1438 if self.page_count == 0 or (self.page_count == 1 and not show_if_single_page):
1441 if self.page_count == 0 or (self.page_count == 1 and not show_if_single_page):
1439 return ''
1442 return ''
1440
1443
1441 from string import Template
1444 from string import Template
1442 # Replace ~...~ in token format by range of pages
1445 # Replace ~...~ in token format by range of pages
1443 result = re.sub(r'~(\d+)~', self._range, format)
1446 result = re.sub(r'~(\d+)~', self._range, format)
1444
1447
1445 # Interpolate '%' variables
1448 # Interpolate '%' variables
1446 result = Template(result).safe_substitute({
1449 result = Template(result).safe_substitute({
1447 'first_page': self.first_page,
1450 'first_page': self.first_page,
1448 'last_page': self.last_page,
1451 'last_page': self.last_page,
1449 'page': self.page,
1452 'page': self.page,
1450 'page_count': self.page_count,
1453 'page_count': self.page_count,
1451 'items_per_page': self.items_per_page,
1454 'items_per_page': self.items_per_page,
1452 'first_item': self.first_item,
1455 'first_item': self.first_item,
1453 'last_item': self.last_item,
1456 'last_item': self.last_item,
1454 'item_count': self.item_count,
1457 'item_count': self.item_count,
1455 'link_first': self.page > self.first_page and \
1458 'link_first': self.page > self.first_page and \
1456 self._pagerlink(self.first_page, symbol_first) or '',
1459 self._pagerlink(self.first_page, symbol_first) or '',
1457 'link_last': self.page < self.last_page and \
1460 'link_last': self.page < self.last_page and \
1458 self._pagerlink(self.last_page, symbol_last) or '',
1461 self._pagerlink(self.last_page, symbol_last) or '',
1459 'link_previous': self.previous_page and \
1462 'link_previous': self.previous_page and \
1460 self._pagerlink(self.previous_page, symbol_previous) \
1463 self._pagerlink(self.previous_page, symbol_previous) \
1461 or HTML.span(symbol_previous, class_="pg-previous disabled"),
1464 or HTML.span(symbol_previous, class_="pg-previous disabled"),
1462 'link_next': self.next_page and \
1465 'link_next': self.next_page and \
1463 self._pagerlink(self.next_page, symbol_next) \
1466 self._pagerlink(self.next_page, symbol_next) \
1464 or HTML.span(symbol_next, class_="pg-next disabled")
1467 or HTML.span(symbol_next, class_="pg-next disabled")
1465 })
1468 })
1466
1469
1467 return literal(result)
1470 return literal(result)
1468
1471
1469
1472
1470 #==============================================================================
1473 #==============================================================================
1471 # REPO PAGER, PAGER FOR REPOSITORY
1474 # REPO PAGER, PAGER FOR REPOSITORY
1472 #==============================================================================
1475 #==============================================================================
1473 class RepoPage(Page):
1476 class RepoPage(Page):
1474
1477
1475 def __init__(self, collection, page=1, items_per_page=20,
1478 def __init__(self, collection, page=1, items_per_page=20,
1476 item_count=None, url=None, **kwargs):
1479 item_count=None, url=None, **kwargs):
1477
1480
1478 """Create a "RepoPage" instance. special pager for paging
1481 """Create a "RepoPage" instance. special pager for paging
1479 repository
1482 repository
1480 """
1483 """
1481 self._url_generator = url
1484 self._url_generator = url
1482
1485
1483 # Safe the kwargs class-wide so they can be used in the pager() method
1486 # Safe the kwargs class-wide so they can be used in the pager() method
1484 self.kwargs = kwargs
1487 self.kwargs = kwargs
1485
1488
1486 # Save a reference to the collection
1489 # Save a reference to the collection
1487 self.original_collection = collection
1490 self.original_collection = collection
1488
1491
1489 self.collection = collection
1492 self.collection = collection
1490
1493
1491 # The self.page is the number of the current page.
1494 # The self.page is the number of the current page.
1492 # The first page has the number 1!
1495 # The first page has the number 1!
1493 try:
1496 try:
1494 self.page = int(page) # make it int() if we get it as a string
1497 self.page = int(page) # make it int() if we get it as a string
1495 except (ValueError, TypeError):
1498 except (ValueError, TypeError):
1496 self.page = 1
1499 self.page = 1
1497
1500
1498 self.items_per_page = items_per_page
1501 self.items_per_page = items_per_page
1499
1502
1500 # Unless the user tells us how many items the collections has
1503 # Unless the user tells us how many items the collections has
1501 # we calculate that ourselves.
1504 # we calculate that ourselves.
1502 if item_count is not None:
1505 if item_count is not None:
1503 self.item_count = item_count
1506 self.item_count = item_count
1504 else:
1507 else:
1505 self.item_count = len(self.collection)
1508 self.item_count = len(self.collection)
1506
1509
1507 # Compute the number of the first and last available page
1510 # Compute the number of the first and last available page
1508 if self.item_count > 0:
1511 if self.item_count > 0:
1509 self.first_page = 1
1512 self.first_page = 1
1510 self.page_count = int(math.ceil(float(self.item_count) /
1513 self.page_count = int(math.ceil(float(self.item_count) /
1511 self.items_per_page))
1514 self.items_per_page))
1512 self.last_page = self.first_page + self.page_count - 1
1515 self.last_page = self.first_page + self.page_count - 1
1513
1516
1514 # Make sure that the requested page number is the range of
1517 # Make sure that the requested page number is the range of
1515 # valid pages
1518 # valid pages
1516 if self.page > self.last_page:
1519 if self.page > self.last_page:
1517 self.page = self.last_page
1520 self.page = self.last_page
1518 elif self.page < self.first_page:
1521 elif self.page < self.first_page:
1519 self.page = self.first_page
1522 self.page = self.first_page
1520
1523
1521 # Note: the number of items on this page can be less than
1524 # Note: the number of items on this page can be less than
1522 # items_per_page if the last page is not full
1525 # items_per_page if the last page is not full
1523 self.first_item = max(0, (self.item_count) - (self.page *
1526 self.first_item = max(0, (self.item_count) - (self.page *
1524 items_per_page))
1527 items_per_page))
1525 self.last_item = ((self.item_count - 1) - items_per_page *
1528 self.last_item = ((self.item_count - 1) - items_per_page *
1526 (self.page - 1))
1529 (self.page - 1))
1527
1530
1528 self.items = list(self.collection[self.first_item:self.last_item + 1])
1531 self.items = list(self.collection[self.first_item:self.last_item + 1])
1529
1532
1530 # Links to previous and next page
1533 # Links to previous and next page
1531 if self.page > self.first_page:
1534 if self.page > self.first_page:
1532 self.previous_page = self.page - 1
1535 self.previous_page = self.page - 1
1533 else:
1536 else:
1534 self.previous_page = None
1537 self.previous_page = None
1535
1538
1536 if self.page < self.last_page:
1539 if self.page < self.last_page:
1537 self.next_page = self.page + 1
1540 self.next_page = self.page + 1
1538 else:
1541 else:
1539 self.next_page = None
1542 self.next_page = None
1540
1543
1541 # No items available
1544 # No items available
1542 else:
1545 else:
1543 self.first_page = None
1546 self.first_page = None
1544 self.page_count = 0
1547 self.page_count = 0
1545 self.last_page = None
1548 self.last_page = None
1546 self.first_item = None
1549 self.first_item = None
1547 self.last_item = None
1550 self.last_item = None
1548 self.previous_page = None
1551 self.previous_page = None
1549 self.next_page = None
1552 self.next_page = None
1550 self.items = []
1553 self.items = []
1551
1554
1552 # This is a subclass of the 'list' type. Initialise the list now.
1555 # This is a subclass of the 'list' type. Initialise the list now.
1553 list.__init__(self, reversed(self.items))
1556 list.__init__(self, reversed(self.items))
1554
1557
1555
1558
1556 def breadcrumb_repo_link(repo):
1559 def breadcrumb_repo_link(repo):
1557 """
1560 """
1558 Makes a breadcrumbs path link to repo
1561 Makes a breadcrumbs path link to repo
1559
1562
1560 ex::
1563 ex::
1561 group >> subgroup >> repo
1564 group >> subgroup >> repo
1562
1565
1563 :param repo: a Repository instance
1566 :param repo: a Repository instance
1564 """
1567 """
1565
1568
1566 path = [
1569 path = [
1567 link_to(group.name, route_path('repo_group_home', repo_group_name=group.group_name))
1570 link_to(group.name, route_path('repo_group_home', repo_group_name=group.group_name))
1568 for group in repo.groups_with_parents
1571 for group in repo.groups_with_parents
1569 ] + [
1572 ] + [
1570 link_to(repo.just_name, route_path('repo_summary', repo_name=repo.repo_name))
1573 link_to(repo.just_name, route_path('repo_summary', repo_name=repo.repo_name))
1571 ]
1574 ]
1572
1575
1573 return literal(' &raquo; '.join(path))
1576 return literal(' &raquo; '.join(path))
1574
1577
1575
1578
1576 def format_byte_size_binary(file_size):
1579 def format_byte_size_binary(file_size):
1577 """
1580 """
1578 Formats file/folder sizes to standard.
1581 Formats file/folder sizes to standard.
1579 """
1582 """
1580 if file_size is None:
1583 if file_size is None:
1581 file_size = 0
1584 file_size = 0
1582
1585
1583 formatted_size = format_byte_size(file_size, binary=True)
1586 formatted_size = format_byte_size(file_size, binary=True)
1584 return formatted_size
1587 return formatted_size
1585
1588
1586
1589
1587 def urlify_text(text_, safe=True):
1590 def urlify_text(text_, safe=True):
1588 """
1591 """
1589 Extrac urls from text and make html links out of them
1592 Extrac urls from text and make html links out of them
1590
1593
1591 :param text_:
1594 :param text_:
1592 """
1595 """
1593
1596
1594 url_pat = re.compile(r'''(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@#.&+]'''
1597 url_pat = re.compile(r'''(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@#.&+]'''
1595 '''|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)''')
1598 '''|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)''')
1596
1599
1597 def url_func(match_obj):
1600 def url_func(match_obj):
1598 url_full = match_obj.groups()[0]
1601 url_full = match_obj.groups()[0]
1599 return '<a href="%(url)s">%(url)s</a>' % ({'url': url_full})
1602 return '<a href="%(url)s">%(url)s</a>' % ({'url': url_full})
1600 _newtext = url_pat.sub(url_func, text_)
1603 _newtext = url_pat.sub(url_func, text_)
1601 if safe:
1604 if safe:
1602 return literal(_newtext)
1605 return literal(_newtext)
1603 return _newtext
1606 return _newtext
1604
1607
1605
1608
1606 def urlify_commits(text_, repository):
1609 def urlify_commits(text_, repository):
1607 """
1610 """
1608 Extract commit ids from text and make link from them
1611 Extract commit ids from text and make link from them
1609
1612
1610 :param text_:
1613 :param text_:
1611 :param repository: repo name to build the URL with
1614 :param repository: repo name to build the URL with
1612 """
1615 """
1613
1616
1614 URL_PAT = re.compile(r'(^|\s)([0-9a-fA-F]{12,40})($|\s)')
1617 URL_PAT = re.compile(r'(^|\s)([0-9a-fA-F]{12,40})($|\s)')
1615
1618
1616 def url_func(match_obj):
1619 def url_func(match_obj):
1617 commit_id = match_obj.groups()[1]
1620 commit_id = match_obj.groups()[1]
1618 pref = match_obj.groups()[0]
1621 pref = match_obj.groups()[0]
1619 suf = match_obj.groups()[2]
1622 suf = match_obj.groups()[2]
1620
1623
1621 tmpl = (
1624 tmpl = (
1622 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1625 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1623 '%(commit_id)s</a>%(suf)s'
1626 '%(commit_id)s</a>%(suf)s'
1624 )
1627 )
1625 return tmpl % {
1628 return tmpl % {
1626 'pref': pref,
1629 'pref': pref,
1627 'cls': 'revision-link',
1630 'cls': 'revision-link',
1628 'url': route_url('repo_commit', repo_name=repository,
1631 'url': route_url('repo_commit', repo_name=repository,
1629 commit_id=commit_id),
1632 commit_id=commit_id),
1630 'commit_id': commit_id,
1633 'commit_id': commit_id,
1631 'suf': suf
1634 'suf': suf
1632 }
1635 }
1633
1636
1634 newtext = URL_PAT.sub(url_func, text_)
1637 newtext = URL_PAT.sub(url_func, text_)
1635
1638
1636 return newtext
1639 return newtext
1637
1640
1638
1641
1639 def _process_url_func(match_obj, repo_name, uid, entry,
1642 def _process_url_func(match_obj, repo_name, uid, entry,
1640 return_raw_data=False, link_format='html'):
1643 return_raw_data=False, link_format='html'):
1641 pref = ''
1644 pref = ''
1642 if match_obj.group().startswith(' '):
1645 if match_obj.group().startswith(' '):
1643 pref = ' '
1646 pref = ' '
1644
1647
1645 issue_id = ''.join(match_obj.groups())
1648 issue_id = ''.join(match_obj.groups())
1646
1649
1647 if link_format == 'html':
1650 if link_format == 'html':
1648 tmpl = (
1651 tmpl = (
1649 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1652 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1650 '%(issue-prefix)s%(id-repr)s'
1653 '%(issue-prefix)s%(id-repr)s'
1651 '</a>')
1654 '</a>')
1652 elif link_format == 'rst':
1655 elif link_format == 'rst':
1653 tmpl = '`%(issue-prefix)s%(id-repr)s <%(url)s>`_'
1656 tmpl = '`%(issue-prefix)s%(id-repr)s <%(url)s>`_'
1654 elif link_format == 'markdown':
1657 elif link_format == 'markdown':
1655 tmpl = '[%(issue-prefix)s%(id-repr)s](%(url)s)'
1658 tmpl = '[%(issue-prefix)s%(id-repr)s](%(url)s)'
1656 else:
1659 else:
1657 raise ValueError('Bad link_format:{}'.format(link_format))
1660 raise ValueError('Bad link_format:{}'.format(link_format))
1658
1661
1659 (repo_name_cleaned,
1662 (repo_name_cleaned,
1660 parent_group_name) = RepoGroupModel().\
1663 parent_group_name) = RepoGroupModel().\
1661 _get_group_name_and_parent(repo_name)
1664 _get_group_name_and_parent(repo_name)
1662
1665
1663 # variables replacement
1666 # variables replacement
1664 named_vars = {
1667 named_vars = {
1665 'id': issue_id,
1668 'id': issue_id,
1666 'repo': repo_name,
1669 'repo': repo_name,
1667 'repo_name': repo_name_cleaned,
1670 'repo_name': repo_name_cleaned,
1668 'group_name': parent_group_name
1671 'group_name': parent_group_name
1669 }
1672 }
1670 # named regex variables
1673 # named regex variables
1671 named_vars.update(match_obj.groupdict())
1674 named_vars.update(match_obj.groupdict())
1672 _url = string.Template(entry['url']).safe_substitute(**named_vars)
1675 _url = string.Template(entry['url']).safe_substitute(**named_vars)
1673
1676
1674 data = {
1677 data = {
1675 'pref': pref,
1678 'pref': pref,
1676 'cls': 'issue-tracker-link',
1679 'cls': 'issue-tracker-link',
1677 'url': _url,
1680 'url': _url,
1678 'id-repr': issue_id,
1681 'id-repr': issue_id,
1679 'issue-prefix': entry['pref'],
1682 'issue-prefix': entry['pref'],
1680 'serv': entry['url'],
1683 'serv': entry['url'],
1681 }
1684 }
1682 if return_raw_data:
1685 if return_raw_data:
1683 return {
1686 return {
1684 'id': issue_id,
1687 'id': issue_id,
1685 'url': _url
1688 'url': _url
1686 }
1689 }
1687 return tmpl % data
1690 return tmpl % data
1688
1691
1689
1692
1690 def get_active_pattern_entries(repo_name):
1693 def get_active_pattern_entries(repo_name):
1691 repo = None
1694 repo = None
1692 if repo_name:
1695 if repo_name:
1693 # Retrieving repo_name to avoid invalid repo_name to explode on
1696 # Retrieving repo_name to avoid invalid repo_name to explode on
1694 # IssueTrackerSettingsModel but still passing invalid name further down
1697 # IssueTrackerSettingsModel but still passing invalid name further down
1695 repo = Repository.get_by_repo_name(repo_name, cache=True)
1698 repo = Repository.get_by_repo_name(repo_name, cache=True)
1696
1699
1697 settings_model = IssueTrackerSettingsModel(repo=repo)
1700 settings_model = IssueTrackerSettingsModel(repo=repo)
1698 active_entries = settings_model.get_settings(cache=True)
1701 active_entries = settings_model.get_settings(cache=True)
1699 return active_entries
1702 return active_entries
1700
1703
1701
1704
1702 def process_patterns(text_string, repo_name, link_format='html',
1705 def process_patterns(text_string, repo_name, link_format='html',
1703 active_entries=None):
1706 active_entries=None):
1704
1707
1705 allowed_formats = ['html', 'rst', 'markdown']
1708 allowed_formats = ['html', 'rst', 'markdown']
1706 if link_format not in allowed_formats:
1709 if link_format not in allowed_formats:
1707 raise ValueError('Link format can be only one of:{} got {}'.format(
1710 raise ValueError('Link format can be only one of:{} got {}'.format(
1708 allowed_formats, link_format))
1711 allowed_formats, link_format))
1709
1712
1710 active_entries = active_entries or get_active_pattern_entries(repo_name)
1713 active_entries = active_entries or get_active_pattern_entries(repo_name)
1711 issues_data = []
1714 issues_data = []
1712 newtext = text_string
1715 newtext = text_string
1713
1716
1714 for uid, entry in active_entries.items():
1717 for uid, entry in active_entries.items():
1715 log.debug('found issue tracker entry with uid %s', uid)
1718 log.debug('found issue tracker entry with uid %s', uid)
1716
1719
1717 if not (entry['pat'] and entry['url']):
1720 if not (entry['pat'] and entry['url']):
1718 log.debug('skipping due to missing data')
1721 log.debug('skipping due to missing data')
1719 continue
1722 continue
1720
1723
1721 log.debug('issue tracker entry: uid: `%s` PAT:%s URL:%s PREFIX:%s',
1724 log.debug('issue tracker entry: uid: `%s` PAT:%s URL:%s PREFIX:%s',
1722 uid, entry['pat'], entry['url'], entry['pref'])
1725 uid, entry['pat'], entry['url'], entry['pref'])
1723
1726
1724 try:
1727 try:
1725 pattern = re.compile(r'%s' % entry['pat'])
1728 pattern = re.compile(r'%s' % entry['pat'])
1726 except re.error:
1729 except re.error:
1727 log.exception(
1730 log.exception(
1728 'issue tracker pattern: `%s` failed to compile',
1731 'issue tracker pattern: `%s` failed to compile',
1729 entry['pat'])
1732 entry['pat'])
1730 continue
1733 continue
1731
1734
1732 data_func = partial(
1735 data_func = partial(
1733 _process_url_func, repo_name=repo_name, entry=entry, uid=uid,
1736 _process_url_func, repo_name=repo_name, entry=entry, uid=uid,
1734 return_raw_data=True)
1737 return_raw_data=True)
1735
1738
1736 for match_obj in pattern.finditer(text_string):
1739 for match_obj in pattern.finditer(text_string):
1737 issues_data.append(data_func(match_obj))
1740 issues_data.append(data_func(match_obj))
1738
1741
1739 url_func = partial(
1742 url_func = partial(
1740 _process_url_func, repo_name=repo_name, entry=entry, uid=uid,
1743 _process_url_func, repo_name=repo_name, entry=entry, uid=uid,
1741 link_format=link_format)
1744 link_format=link_format)
1742
1745
1743 newtext = pattern.sub(url_func, newtext)
1746 newtext = pattern.sub(url_func, newtext)
1744 log.debug('processed prefix:uid `%s`', uid)
1747 log.debug('processed prefix:uid `%s`', uid)
1745
1748
1746 return newtext, issues_data
1749 return newtext, issues_data
1747
1750
1748
1751
1749 def urlify_commit_message(commit_text, repository=None,
1752 def urlify_commit_message(commit_text, repository=None,
1750 active_pattern_entries=None):
1753 active_pattern_entries=None):
1751 """
1754 """
1752 Parses given text message and makes proper links.
1755 Parses given text message and makes proper links.
1753 issues are linked to given issue-server, and rest is a commit link
1756 issues are linked to given issue-server, and rest is a commit link
1754
1757
1755 :param commit_text:
1758 :param commit_text:
1756 :param repository:
1759 :param repository:
1757 """
1760 """
1758 def escaper(string):
1761 def escaper(string):
1759 return string.replace('<', '&lt;').replace('>', '&gt;')
1762 return string.replace('<', '&lt;').replace('>', '&gt;')
1760
1763
1761 newtext = escaper(commit_text)
1764 newtext = escaper(commit_text)
1762
1765
1763 # extract http/https links and make them real urls
1766 # extract http/https links and make them real urls
1764 newtext = urlify_text(newtext, safe=False)
1767 newtext = urlify_text(newtext, safe=False)
1765
1768
1766 # urlify commits - extract commit ids and make link out of them, if we have
1769 # urlify commits - extract commit ids and make link out of them, if we have
1767 # the scope of repository present.
1770 # the scope of repository present.
1768 if repository:
1771 if repository:
1769 newtext = urlify_commits(newtext, repository)
1772 newtext = urlify_commits(newtext, repository)
1770
1773
1771 # process issue tracker patterns
1774 # process issue tracker patterns
1772 newtext, issues = process_patterns(newtext, repository or '',
1775 newtext, issues = process_patterns(newtext, repository or '',
1773 active_entries=active_pattern_entries)
1776 active_entries=active_pattern_entries)
1774
1777
1775 return literal(newtext)
1778 return literal(newtext)
1776
1779
1777
1780
1778 def render_binary(repo_name, file_obj):
1781 def render_binary(repo_name, file_obj):
1779 """
1782 """
1780 Choose how to render a binary file
1783 Choose how to render a binary file
1781 """
1784 """
1782
1785
1783 filename = file_obj.name
1786 filename = file_obj.name
1784
1787
1785 # images
1788 # images
1786 for ext in ['*.png', '*.jpg', '*.ico', '*.gif']:
1789 for ext in ['*.png', '*.jpg', '*.ico', '*.gif']:
1787 if fnmatch.fnmatch(filename, pat=ext):
1790 if fnmatch.fnmatch(filename, pat=ext):
1788 alt = escape(filename)
1791 alt = escape(filename)
1789 src = route_path(
1792 src = route_path(
1790 'repo_file_raw', repo_name=repo_name,
1793 'repo_file_raw', repo_name=repo_name,
1791 commit_id=file_obj.commit.raw_id,
1794 commit_id=file_obj.commit.raw_id,
1792 f_path=file_obj.path)
1795 f_path=file_obj.path)
1793 return literal(
1796 return literal(
1794 '<img class="rendered-binary" alt="{}" src="{}">'.format(alt, src))
1797 '<img class="rendered-binary" alt="{}" src="{}">'.format(alt, src))
1795
1798
1796
1799
1797 def renderer_from_filename(filename, exclude=None):
1800 def renderer_from_filename(filename, exclude=None):
1798 """
1801 """
1799 choose a renderer based on filename, this works only for text based files
1802 choose a renderer based on filename, this works only for text based files
1800 """
1803 """
1801
1804
1802 # ipython
1805 # ipython
1803 for ext in ['*.ipynb']:
1806 for ext in ['*.ipynb']:
1804 if fnmatch.fnmatch(filename, pat=ext):
1807 if fnmatch.fnmatch(filename, pat=ext):
1805 return 'jupyter'
1808 return 'jupyter'
1806
1809
1807 is_markup = MarkupRenderer.renderer_from_filename(filename, exclude=exclude)
1810 is_markup = MarkupRenderer.renderer_from_filename(filename, exclude=exclude)
1808 if is_markup:
1811 if is_markup:
1809 return is_markup
1812 return is_markup
1810 return None
1813 return None
1811
1814
1812
1815
1813 def render(source, renderer='rst', mentions=False, relative_urls=None,
1816 def render(source, renderer='rst', mentions=False, relative_urls=None,
1814 repo_name=None):
1817 repo_name=None):
1815
1818
1816 def maybe_convert_relative_links(html_source):
1819 def maybe_convert_relative_links(html_source):
1817 if relative_urls:
1820 if relative_urls:
1818 return relative_links(html_source, relative_urls)
1821 return relative_links(html_source, relative_urls)
1819 return html_source
1822 return html_source
1820
1823
1821 if renderer == 'plain':
1824 if renderer == 'plain':
1822 return literal(
1825 return literal(
1823 MarkupRenderer.plain(source, leading_newline=False))
1826 MarkupRenderer.plain(source, leading_newline=False))
1824
1827
1825 elif renderer == 'rst':
1828 elif renderer == 'rst':
1826 if repo_name:
1829 if repo_name:
1827 # process patterns on comments if we pass in repo name
1830 # process patterns on comments if we pass in repo name
1828 source, issues = process_patterns(
1831 source, issues = process_patterns(
1829 source, repo_name, link_format='rst')
1832 source, repo_name, link_format='rst')
1830
1833
1831 return literal(
1834 return literal(
1832 '<div class="rst-block">%s</div>' %
1835 '<div class="rst-block">%s</div>' %
1833 maybe_convert_relative_links(
1836 maybe_convert_relative_links(
1834 MarkupRenderer.rst(source, mentions=mentions)))
1837 MarkupRenderer.rst(source, mentions=mentions)))
1835
1838
1836 elif renderer == 'markdown':
1839 elif renderer == 'markdown':
1837 if repo_name:
1840 if repo_name:
1838 # process patterns on comments if we pass in repo name
1841 # process patterns on comments if we pass in repo name
1839 source, issues = process_patterns(
1842 source, issues = process_patterns(
1840 source, repo_name, link_format='markdown')
1843 source, repo_name, link_format='markdown')
1841
1844
1842 return literal(
1845 return literal(
1843 '<div class="markdown-block">%s</div>' %
1846 '<div class="markdown-block">%s</div>' %
1844 maybe_convert_relative_links(
1847 maybe_convert_relative_links(
1845 MarkupRenderer.markdown(source, flavored=True,
1848 MarkupRenderer.markdown(source, flavored=True,
1846 mentions=mentions)))
1849 mentions=mentions)))
1847
1850
1848 elif renderer == 'jupyter':
1851 elif renderer == 'jupyter':
1849 return literal(
1852 return literal(
1850 '<div class="ipynb">%s</div>' %
1853 '<div class="ipynb">%s</div>' %
1851 maybe_convert_relative_links(
1854 maybe_convert_relative_links(
1852 MarkupRenderer.jupyter(source)))
1855 MarkupRenderer.jupyter(source)))
1853
1856
1854 # None means just show the file-source
1857 # None means just show the file-source
1855 return None
1858 return None
1856
1859
1857
1860
1858 def commit_status(repo, commit_id):
1861 def commit_status(repo, commit_id):
1859 return ChangesetStatusModel().get_status(repo, commit_id)
1862 return ChangesetStatusModel().get_status(repo, commit_id)
1860
1863
1861
1864
1862 def commit_status_lbl(commit_status):
1865 def commit_status_lbl(commit_status):
1863 return dict(ChangesetStatus.STATUSES).get(commit_status)
1866 return dict(ChangesetStatus.STATUSES).get(commit_status)
1864
1867
1865
1868
1866 def commit_time(repo_name, commit_id):
1869 def commit_time(repo_name, commit_id):
1867 repo = Repository.get_by_repo_name(repo_name)
1870 repo = Repository.get_by_repo_name(repo_name)
1868 commit = repo.get_commit(commit_id=commit_id)
1871 commit = repo.get_commit(commit_id=commit_id)
1869 return commit.date
1872 return commit.date
1870
1873
1871
1874
1872 def get_permission_name(key):
1875 def get_permission_name(key):
1873 return dict(Permission.PERMS).get(key)
1876 return dict(Permission.PERMS).get(key)
1874
1877
1875
1878
1876 def journal_filter_help(request):
1879 def journal_filter_help(request):
1877 _ = request.translate
1880 _ = request.translate
1878 from rhodecode.lib.audit_logger import ACTIONS
1881 from rhodecode.lib.audit_logger import ACTIONS
1879 actions = '\n'.join(textwrap.wrap(', '.join(sorted(ACTIONS.keys())), 80))
1882 actions = '\n'.join(textwrap.wrap(', '.join(sorted(ACTIONS.keys())), 80))
1880
1883
1881 return _(
1884 return _(
1882 'Example filter terms:\n' +
1885 'Example filter terms:\n' +
1883 ' repository:vcs\n' +
1886 ' repository:vcs\n' +
1884 ' username:marcin\n' +
1887 ' username:marcin\n' +
1885 ' username:(NOT marcin)\n' +
1888 ' username:(NOT marcin)\n' +
1886 ' action:*push*\n' +
1889 ' action:*push*\n' +
1887 ' ip:127.0.0.1\n' +
1890 ' ip:127.0.0.1\n' +
1888 ' date:20120101\n' +
1891 ' date:20120101\n' +
1889 ' date:[20120101100000 TO 20120102]\n' +
1892 ' date:[20120101100000 TO 20120102]\n' +
1890 '\n' +
1893 '\n' +
1891 'Actions: {actions}\n' +
1894 'Actions: {actions}\n' +
1892 '\n' +
1895 '\n' +
1893 'Generate wildcards using \'*\' character:\n' +
1896 'Generate wildcards using \'*\' character:\n' +
1894 ' "repository:vcs*" - search everything starting with \'vcs\'\n' +
1897 ' "repository:vcs*" - search everything starting with \'vcs\'\n' +
1895 ' "repository:*vcs*" - search for repository containing \'vcs\'\n' +
1898 ' "repository:*vcs*" - search for repository containing \'vcs\'\n' +
1896 '\n' +
1899 '\n' +
1897 'Optional AND / OR operators in queries\n' +
1900 'Optional AND / OR operators in queries\n' +
1898 ' "repository:vcs OR repository:test"\n' +
1901 ' "repository:vcs OR repository:test"\n' +
1899 ' "username:test AND repository:test*"\n'
1902 ' "username:test AND repository:test*"\n'
1900 ).format(actions=actions)
1903 ).format(actions=actions)
1901
1904
1902
1905
1903 def search_filter_help(searcher, request):
1906 def search_filter_help(searcher, request):
1904 _ = request.translate
1907 _ = request.translate
1905
1908
1906 terms = ''
1909 terms = ''
1907 return _(
1910 return _(
1908 'Example filter terms for `{searcher}` search:\n' +
1911 'Example filter terms for `{searcher}` search:\n' +
1909 '{terms}\n' +
1912 '{terms}\n' +
1910 'Generate wildcards using \'*\' character:\n' +
1913 'Generate wildcards using \'*\' character:\n' +
1911 ' "repo_name:vcs*" - search everything starting with \'vcs\'\n' +
1914 ' "repo_name:vcs*" - search everything starting with \'vcs\'\n' +
1912 ' "repo_name:*vcs*" - search for repository containing \'vcs\'\n' +
1915 ' "repo_name:*vcs*" - search for repository containing \'vcs\'\n' +
1913 '\n' +
1916 '\n' +
1914 'Optional AND / OR operators in queries\n' +
1917 'Optional AND / OR operators in queries\n' +
1915 ' "repo_name:vcs OR repo_name:test"\n' +
1918 ' "repo_name:vcs OR repo_name:test"\n' +
1916 ' "owner:test AND repo_name:test*"\n' +
1919 ' "owner:test AND repo_name:test*"\n' +
1917 'More: {search_doc}'
1920 'More: {search_doc}'
1918 ).format(searcher=searcher.name,
1921 ).format(searcher=searcher.name,
1919 terms=terms, search_doc=searcher.query_lang_doc)
1922 terms=terms, search_doc=searcher.query_lang_doc)
1920
1923
1921
1924
1922 def not_mapped_error(repo_name):
1925 def not_mapped_error(repo_name):
1923 from rhodecode.translation import _
1926 from rhodecode.translation import _
1924 flash(_('%s repository is not mapped to db perhaps'
1927 flash(_('%s repository is not mapped to db perhaps'
1925 ' it was created or renamed from the filesystem'
1928 ' it was created or renamed from the filesystem'
1926 ' please run the application again'
1929 ' please run the application again'
1927 ' in order to rescan repositories') % repo_name, category='error')
1930 ' in order to rescan repositories') % repo_name, category='error')
1928
1931
1929
1932
1930 def ip_range(ip_addr):
1933 def ip_range(ip_addr):
1931 from rhodecode.model.db import UserIpMap
1934 from rhodecode.model.db import UserIpMap
1932 s, e = UserIpMap._get_ip_range(ip_addr)
1935 s, e = UserIpMap._get_ip_range(ip_addr)
1933 return '%s - %s' % (s, e)
1936 return '%s - %s' % (s, e)
1934
1937
1935
1938
1936 def form(url, method='post', needs_csrf_token=True, **attrs):
1939 def form(url, method='post', needs_csrf_token=True, **attrs):
1937 """Wrapper around webhelpers.tags.form to prevent CSRF attacks."""
1940 """Wrapper around webhelpers.tags.form to prevent CSRF attacks."""
1938 if method.lower() != 'get' and needs_csrf_token:
1941 if method.lower() != 'get' and needs_csrf_token:
1939 raise Exception(
1942 raise Exception(
1940 'Forms to POST/PUT/DELETE endpoints should have (in general) a ' +
1943 'Forms to POST/PUT/DELETE endpoints should have (in general) a ' +
1941 'CSRF token. If the endpoint does not require such token you can ' +
1944 'CSRF token. If the endpoint does not require such token you can ' +
1942 'explicitly set the parameter needs_csrf_token to false.')
1945 'explicitly set the parameter needs_csrf_token to false.')
1943
1946
1944 return wh_form(url, method=method, **attrs)
1947 return wh_form(url, method=method, **attrs)
1945
1948
1946
1949
1947 def secure_form(form_url, method="POST", multipart=False, **attrs):
1950 def secure_form(form_url, method="POST", multipart=False, **attrs):
1948 """Start a form tag that points the action to an url. This
1951 """Start a form tag that points the action to an url. This
1949 form tag will also include the hidden field containing
1952 form tag will also include the hidden field containing
1950 the auth token.
1953 the auth token.
1951
1954
1952 The url options should be given either as a string, or as a
1955 The url options should be given either as a string, or as a
1953 ``url()`` function. The method for the form defaults to POST.
1956 ``url()`` function. The method for the form defaults to POST.
1954
1957
1955 Options:
1958 Options:
1956
1959
1957 ``multipart``
1960 ``multipart``
1958 If set to True, the enctype is set to "multipart/form-data".
1961 If set to True, the enctype is set to "multipart/form-data".
1959 ``method``
1962 ``method``
1960 The method to use when submitting the form, usually either
1963 The method to use when submitting the form, usually either
1961 "GET" or "POST". If "PUT", "DELETE", or another verb is used, a
1964 "GET" or "POST". If "PUT", "DELETE", or another verb is used, a
1962 hidden input with name _method is added to simulate the verb
1965 hidden input with name _method is added to simulate the verb
1963 over POST.
1966 over POST.
1964
1967
1965 """
1968 """
1966 from webhelpers.pylonslib.secure_form import insecure_form
1969 from webhelpers.pylonslib.secure_form import insecure_form
1967
1970
1968 if 'request' in attrs:
1971 if 'request' in attrs:
1969 session = attrs['request'].session
1972 session = attrs['request'].session
1970 del attrs['request']
1973 del attrs['request']
1971 else:
1974 else:
1972 raise ValueError(
1975 raise ValueError(
1973 'Calling this form requires request= to be passed as argument')
1976 'Calling this form requires request= to be passed as argument')
1974
1977
1975 form = insecure_form(form_url, method, multipart, **attrs)
1978 form = insecure_form(form_url, method, multipart, **attrs)
1976 token = literal(
1979 token = literal(
1977 '<input type="hidden" id="{}" name="{}" value="{}">'.format(
1980 '<input type="hidden" id="{}" name="{}" value="{}">'.format(
1978 csrf_token_key, csrf_token_key, get_csrf_token(session)))
1981 csrf_token_key, csrf_token_key, get_csrf_token(session)))
1979
1982
1980 return literal("%s\n%s" % (form, token))
1983 return literal("%s\n%s" % (form, token))
1981
1984
1982
1985
1983 def dropdownmenu(name, selected, options, enable_filter=False, **attrs):
1986 def dropdownmenu(name, selected, options, enable_filter=False, **attrs):
1984 select_html = select(name, selected, options, **attrs)
1987 select_html = select(name, selected, options, **attrs)
1985 select2 = """
1988 select2 = """
1986 <script>
1989 <script>
1987 $(document).ready(function() {
1990 $(document).ready(function() {
1988 $('#%s').select2({
1991 $('#%s').select2({
1989 containerCssClass: 'drop-menu',
1992 containerCssClass: 'drop-menu',
1990 dropdownCssClass: 'drop-menu-dropdown',
1993 dropdownCssClass: 'drop-menu-dropdown',
1991 dropdownAutoWidth: true%s
1994 dropdownAutoWidth: true%s
1992 });
1995 });
1993 });
1996 });
1994 </script>
1997 </script>
1995 """
1998 """
1996 filter_option = """,
1999 filter_option = """,
1997 minimumResultsForSearch: -1
2000 minimumResultsForSearch: -1
1998 """
2001 """
1999 input_id = attrs.get('id') or name
2002 input_id = attrs.get('id') or name
2000 filter_enabled = "" if enable_filter else filter_option
2003 filter_enabled = "" if enable_filter else filter_option
2001 select_script = literal(select2 % (input_id, filter_enabled))
2004 select_script = literal(select2 % (input_id, filter_enabled))
2002
2005
2003 return literal(select_html+select_script)
2006 return literal(select_html+select_script)
2004
2007
2005
2008
2006 def get_visual_attr(tmpl_context_var, attr_name):
2009 def get_visual_attr(tmpl_context_var, attr_name):
2007 """
2010 """
2008 A safe way to get a variable from visual variable of template context
2011 A safe way to get a variable from visual variable of template context
2009
2012
2010 :param tmpl_context_var: instance of tmpl_context, usually present as `c`
2013 :param tmpl_context_var: instance of tmpl_context, usually present as `c`
2011 :param attr_name: name of the attribute we fetch from the c.visual
2014 :param attr_name: name of the attribute we fetch from the c.visual
2012 """
2015 """
2013 visual = getattr(tmpl_context_var, 'visual', None)
2016 visual = getattr(tmpl_context_var, 'visual', None)
2014 if not visual:
2017 if not visual:
2015 return
2018 return
2016 else:
2019 else:
2017 return getattr(visual, attr_name, None)
2020 return getattr(visual, attr_name, None)
2018
2021
2019
2022
2020 def get_last_path_part(file_node):
2023 def get_last_path_part(file_node):
2021 if not file_node.path:
2024 if not file_node.path:
2022 return u''
2025 return u''
2023
2026
2024 path = safe_unicode(file_node.path.split('/')[-1])
2027 path = safe_unicode(file_node.path.split('/')[-1])
2025 return u'../' + path
2028 return u'../' + path
2026
2029
2027
2030
2028 def route_url(*args, **kwargs):
2031 def route_url(*args, **kwargs):
2029 """
2032 """
2030 Wrapper around pyramids `route_url` (fully qualified url) function.
2033 Wrapper around pyramids `route_url` (fully qualified url) function.
2031 """
2034 """
2032 req = get_current_request()
2035 req = get_current_request()
2033 return req.route_url(*args, **kwargs)
2036 return req.route_url(*args, **kwargs)
2034
2037
2035
2038
2036 def route_path(*args, **kwargs):
2039 def route_path(*args, **kwargs):
2037 """
2040 """
2038 Wrapper around pyramids `route_path` function.
2041 Wrapper around pyramids `route_path` function.
2039 """
2042 """
2040 req = get_current_request()
2043 req = get_current_request()
2041 return req.route_path(*args, **kwargs)
2044 return req.route_path(*args, **kwargs)
2042
2045
2043
2046
2044 def route_path_or_none(*args, **kwargs):
2047 def route_path_or_none(*args, **kwargs):
2045 try:
2048 try:
2046 return route_path(*args, **kwargs)
2049 return route_path(*args, **kwargs)
2047 except KeyError:
2050 except KeyError:
2048 return None
2051 return None
2049
2052
2050
2053
2051 def current_route_path(request, **kw):
2054 def current_route_path(request, **kw):
2052 new_args = request.GET.mixed()
2055 new_args = request.GET.mixed()
2053 new_args.update(kw)
2056 new_args.update(kw)
2054 return request.current_route_path(_query=new_args)
2057 return request.current_route_path(_query=new_args)
2055
2058
2056
2059
2057 def api_call_example(method, args):
2060 def api_call_example(method, args):
2058 """
2061 """
2059 Generates an API call example via CURL
2062 Generates an API call example via CURL
2060 """
2063 """
2061 args_json = json.dumps(OrderedDict([
2064 args_json = json.dumps(OrderedDict([
2062 ('id', 1),
2065 ('id', 1),
2063 ('auth_token', 'SECRET'),
2066 ('auth_token', 'SECRET'),
2064 ('method', method),
2067 ('method', method),
2065 ('args', args)
2068 ('args', args)
2066 ]))
2069 ]))
2067 return literal(
2070 return literal(
2068 "curl {api_url} -X POST -H 'content-type:text/plain' --data-binary '{data}'"
2071 "curl {api_url} -X POST -H 'content-type:text/plain' --data-binary '{data}'"
2069 "<br/><br/>SECRET can be found in <a href=\"{token_url}\">auth-tokens</a> page, "
2072 "<br/><br/>SECRET can be found in <a href=\"{token_url}\">auth-tokens</a> page, "
2070 "and needs to be of `api calls` role."
2073 "and needs to be of `api calls` role."
2071 .format(
2074 .format(
2072 api_url=route_url('apiv2'),
2075 api_url=route_url('apiv2'),
2073 token_url=route_url('my_account_auth_tokens'),
2076 token_url=route_url('my_account_auth_tokens'),
2074 data=args_json))
2077 data=args_json))
2075
2078
2076
2079
2077 def notification_description(notification, request):
2080 def notification_description(notification, request):
2078 """
2081 """
2079 Generate notification human readable description based on notification type
2082 Generate notification human readable description based on notification type
2080 """
2083 """
2081 from rhodecode.model.notification import NotificationModel
2084 from rhodecode.model.notification import NotificationModel
2082 return NotificationModel().make_description(
2085 return NotificationModel().make_description(
2083 notification, translate=request.translate)
2086 notification, translate=request.translate)
2084
2087
2085
2088
2086 def go_import_header(request, db_repo=None):
2089 def go_import_header(request, db_repo=None):
2087 """
2090 """
2088 Creates a header for go-import functionality in Go Lang
2091 Creates a header for go-import functionality in Go Lang
2089 """
2092 """
2090
2093
2091 if not db_repo:
2094 if not db_repo:
2092 return
2095 return
2093 if 'go-get' not in request.GET:
2096 if 'go-get' not in request.GET:
2094 return
2097 return
2095
2098
2096 clone_url = db_repo.clone_url()
2099 clone_url = db_repo.clone_url()
2097 prefix = re.split(r'^https?:\/\/', clone_url)[-1]
2100 prefix = re.split(r'^https?:\/\/', clone_url)[-1]
2098 # we have a repo and go-get flag,
2101 # we have a repo and go-get flag,
2099 return literal('<meta name="go-import" content="{} {} {}">'.format(
2102 return literal('<meta name="go-import" content="{} {} {}">'.format(
2100 prefix, db_repo.repo_type, clone_url))
2103 prefix, db_repo.repo_type, clone_url))
2101
2104
2102
2105
2103 def reviewer_as_json(*args, **kwargs):
2106 def reviewer_as_json(*args, **kwargs):
2104 from rhodecode.apps.repository.utils import reviewer_as_json as _reviewer_as_json
2107 from rhodecode.apps.repository.utils import reviewer_as_json as _reviewer_as_json
2105 return _reviewer_as_json(*args, **kwargs)
2108 return _reviewer_as_json(*args, **kwargs)
@@ -1,114 +1,114 b''
1 <!DOCTYPE html>
1 <!DOCTYPE html>
2 <html xmlns="http://www.w3.org/1999/xhtml">
2 <html xmlns="http://www.w3.org/1999/xhtml">
3 <head>
3 <head>
4 <title>Error - 502 Bad Gateway</title>
4 <title>Error - 502 Bad Gateway</title>
5 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
5 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
6 <meta name="robots" content="index, nofollow"/>
6 <meta name="robots" content="index, nofollow"/>
7 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
7 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
8 <style>
8 <style>
9 * {
9 * {
10 box-sizing: border-box;
10 box-sizing: border-box;
11 }
11 }
12 body {
12 body {
13 background:#eeeeee;
13 background:#eeeeee;
14 color: #323232;
14 color: #323232;
15 font-family: "proximanovaregular","Proxima Nova Regular","Proxima Nova",sans-serif;
15 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
16 margin: 0 auto;
16 margin: 0 auto;
17 max-width: 1000px;
17 max-width: 1000px;
18 letter-spacing: .02em;
18 letter-spacing: .02em;
19 font-size: 13px;
19 font-size: 13px;
20 line-height: 1.41em;
20 line-height: 1.41em;
21 }
21 }
22 h1 {
22 h1 {
23 padding: 20px 0;
23 padding: 20px 0;
24 font-size: 1.54em;
24 font-size: 1.54em;
25 }
25 }
26 ul {
26 ul {
27 padding-left: 10px;
27 padding-left: 10px;
28 }
28 }
29 li {
29 li {
30 list-style-type: none;
30 list-style-type: none;
31 }
31 }
32 li:before {
32 li:before {
33 content: "\2014\00A0";
33 content: "\2014\00A0";
34 }
34 }
35 .error_message {
35 .error_message {
36 font-weight: normal;
36 font-weight: normal;
37 }
37 }
38 .logo-container {
38 .logo-container {
39 float: left;
39 float: left;
40 width: 150px;
40 width: 150px;
41 text-align: center;
41 text-align: center;
42 }
42 }
43 a {
43 a {
44 color: #427cc9;
44 color: #427cc9;
45 text-decoration: none;
45 text-decoration: none;
46 outline: none;
46 outline: none;
47 cursor: pointer;
47 cursor: pointer;
48 }
48 }
49 body {
49 body {
50 padding: 10px;
50 padding: 10px;
51 padding-top: 10%;
51 padding-top: 10%;
52
52
53 }
53 }
54 .inner-column {
54 .inner-column {
55 padding: 10px 30px;
55 padding: 10px 30px;
56 width: 33%;
56 width: 33%;
57 float: left;
57 float: left;
58 border-right: 1px solid #dbd9da;
58 border-right: 1px solid #dbd9da;
59
59
60 }
60 }
61 .inner-column:last-child {
61 .inner-column:last-child {
62 border: none;
62 border: none;
63 }
63 }
64 .side {
64 .side {
65 min-height: 220px;
65 min-height: 220px;
66 width: 150px;
66 width: 150px;
67 float: left;
67 float: left;
68 text-align: center;
68 text-align: center;
69 border-right: 1px solid #ddd;
69 border-right: 1px solid #ddd;
70 }
70 }
71 .logo {
71 .logo {
72 width: 120px;
72 width: 120px;
73 height: 150px;
73 height: 150px;
74 }
74 }
75 .main {
75 .main {
76 padding-left: 170px;
76 padding-left: 170px;
77 }
77 }
78 @media (max-width: 979px) {
78 @media (max-width: 979px) {
79 .inner-column {
79 .inner-column {
80 width: 100%;
80 width: 100%;
81 }
81 }
82 }
82 }
83 </style>
83 </style>
84
84
85 </head>
85 </head>
86 <body>
86 <body>
87 <div class="side">
87 <div class="side">
88 <img class="logo" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAScAAAFxCAYAAAAxjW6rAAAACXBIWXMAABcSAAAXEgFnn9JSAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAM9BJREFUeNrsnQtwHVeZ548etmX5dQMJSZx1LANhA+us5YlhSLyLpcCw2AtYXrY2Do9YKqaAhA22h0fBEtZyDdQACcieLFMkM5TkzBRJpgBLvBwYEstbE2cZEixT4RHiwtd5OInz8JUfsmRb1vb/6hy5dX373u6+fU6f7v7/qrquJV/dc7v7nH9/33e+8x0hCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEkGxRx0tAAtLqHDn577YK7xtyjoL8d14ehFCcSE20yAPis0AKkvpdrQzK1z1SvIYoXoTiREppk1YQxGeZFJ/WGL+PsrbcwuW2wAjFiaRQhJTlsypCK8gkg9K6OuSytoZ4aylOhCJkK0qo9lO0KE4kflpdLlhWRKhW0VI/E4oTiQAVD4JFtFj+u5WXpWb3cMjlHg7yklCcSGVaXOJDayg+K0uJF4PwFCcKkZieO0TsIC9FioJFcaIQkcQI1h66hBSnJNImj2XifOCapNslHHRZWHleEoqTLVaREqI2wWA1mXT93GJF64riZAQ1c7ZKnM+uJqQagy53cFAwdkVxitBFU2JESJSuIMWK4kQxIhQrilPy3LQOihGhWFGc4qalRIwYMyJJEasBkbEAe9rFKedy0zoEp/VJ8lGzgUqs8hSn5FlHa+mqkQy5gANps6rSIk5tUoxoHZGsW1X9YjJW1S8SHqtKsjh1uASJsSNCLkRZVP1JdP+SJE65EkEihARz/3YkVahsFaRO59jpHBM87D7a2tomcrkcr4X9xz7n2GR7CMRWy4kum2W0tLRMOxYvXjzt57KP6qEhUSgUiq/Dw8NicHBw6mdinUXVZ1uMyiZxQkLkRgpSjDegtVU4lo9wLKDiz6tWrSr+jN9HTT6fnzoOHTo0JWQQMBIb/a4YVexCFbc4tUi3bYPgLJtRC0gJEQSokvUTB0q03BaX+h0xgpr1g0UV29MiLnHqFAxsG7OClAumLKJE+yCOYEGk9u/fT2vL0LPCObbH4faZFKcW6bZ10m2L3hKC8CxbtmzKKsrcCJKW1Z49e6YEjLGtyOkzaU2ZECfltrXx3oZHxX5wKBFKgyVk0tKie5gsa0qXOMEy2iQYSwptDbmFCK82xYSSjpoxxKHcQ1pZ4S6lmIxNbRUacqd0iFO3dN/ougUUIgSnVayImAeWFURKzR4ylhUIJVKRqXyU4oQRtZPuG4UojYJFC8s3XdLds0qcIEycfXOBmJAKVNM1S5dgqcC7Siwl01gehQUVlTh1SHHKtFWkhAivWZwxyyoIsEOkVNCd1lVxNq/dFnE6KDIW+Ib4QISUe0ariChUwB3WFcQqo7GrJaLGIHkU4gQTYV+WxAivjBWRMK5ghsQKwfHuuMWpV0zmMqXSTYMYdXR0UIxI5GI1MDCQZjcwL62nWMXpqEhJ2gBESIkR3TRi0g3s7++fsqxSlCRaU2C8VnFKdCAcAuQWJEJsQM0CKssqwfSJydSCWMQpcS4dYkcbNmygdUQSZ1XhNWFpC/iyF8UlTomYpYMQrV27lrEjknjcQpUQ9y+0a1eLOFk7S6dKhVCQSNrdvx07dtguVNucY7Npcep2ji02WkidnZ3suYRCZQf4MqFm7WoRp33SeqLLRoiFQtXX12dLjCpUQmZYcYIKHI3rTFVQGxYSBYkQb2BJYdYv5mB6qMXAYcXJeAqBmvbfuHEjZ9kICYia9YNFFUN6AsqprDMlTj1ispicdmAdKbeNEFI7iEkpt89QfCpUSkFYcdIab4JlBAuJbhshZtw+CJVmAsedwoiT1njTpk2bRE9PD3sNIQZBEL29vV1nXCpw3Kk+RCPaLKalS5eK6z/ZzZ5CiGEwyaTZKFgV9A/CiFObrm//8Y9/3HFMx8QfCmfYWwgxjOa4bmCjJow4LdP17VevXi1ac/Wi74/D7CmEGEbX1vMmxUnLt4dLt2DBgsl/N4+LX700xt5CiGE074UY6MODihOC4S26xEnxnssaxF1PsGg8IaZB+SCNBNKOoOKkzea78sorp/387kuE+LvfH2NvIcQgmjfmSKY4zZ8/f9rPsJ5+/sxJcfzMOfYYQgyBHEONuYWBzLKg4rRY17d2u3WK/76wXnx1P4PjhKTEekqm5VSO/3Rxg/jFcyMMjhNCcYr2w4OwcuXKC343t1GI297QKL742FH2GEIMoXnJmG/ls0acvEDsafzcOIPjhBhC84ydb+ULIk7ahKlcvMlN1+JG8a3fHRPPjYyz5xCScK8xUeKkki8rWU+XNdU57t2rvLWEaEZzIqYWy0kbpWkEXtYTAuP/eOAEew8hyWWBDnHSJqfXXHNN1ffAesK6O7p3hOhHY7VZ325dY5IuGKynjftPF927vndcwh5EUsPjjz8+7ec3velNYt68eVM/P//88+Lw4cOef1/6/ijEKe5dXIKI0wJdX+L666/3J7mO5YRDuXcfeeNc9mqSeFDT+zOf+cy03919993i2muvnfr5Rz/6kbjnnns8P6P0/TYbZTrculYbzuwL/35G8ZXuHUkDx48fF9/85jervg+WU1o8xkS5ddVm69xg1u6/LawXPzh8ju4dSTywhiq5awr3ez72sY9d8P8LFy6M9Hthxi6GXVrsE6dqeU6lfHTJTPHzI2N070ii+eMf/yjuu+++4r/hkpXGnbwsp3LilEbqk/ilsazl1tc3FP/91f0FlvUlieQb3/iGb8FRlhMsJFhbOH784x8X3cK0unZBLKc2m87uv17eKL733Fnxp5NCfPHxV8X333kpeztJDLCYlKUEq6lSMNttNUGk3IFxzNB9+tOfFu9973uTJk556y2noC6dm1tfP6mtsJxgQRGSBGDtuAWmu7vbl9Xk9Vn4+0ouId26kAQJhpfy1tc0FoPjALGnhw6fYs8n1rN169YpdwyBZ4hPqbggHuW2rB577LGp47vf/e4FS0xU7CoqNC/+9UWQTTUndHwBlErBrqNhGT5zTqz/5ZgYGa8T82bUi++/61JxRXMDRwAJxYoVKwL/DQRDVxuVPvuDH/xgUcSUgCHXKSowU4dNNjWBDx6s9qbGpHemBY4gwb2786nxYknfTz36MuNPlgJLAHsT6gLxF2RKI2iMwYqnf5RZ07aR5nNLhTiB9y2cIX7y/Bnx+xP1U/Gnzy/LUQ0yBlwlCCAOZFQX+8b73lecCbv88sut+Z5eFo5buBHkhtAqUUdQXIktzhMzdW5XMOo8J4pThHzpLU3iLx+fdO8Qf3rrJbPEOxfO5ojNOBApHBAoW/KD/CwzgTCp9yGeVCkhEoKVxtyn+rScyBWz68WHFp0/HZT2Zf4TUWB2DJZJEvOCKs3EQZhgidlkGdJyKsOHF89y3LuT4vBYQzH+hPwnLG9BoJwQDHIssI0ycBwlbuvH7abdeeedRctJBb+VKGHGLs1xtca0ndD/fsss8dHHTosZDSr+NCy+suIijkwyJVCwomx0g7y+U7UkzbSSOpPizfMbxYcXnc+Q6D90ktUzyQUuntcqfyUE6kj7jBgtJ8PcetVs8ZtjI8XZO4DZu4XNDQyQxwwGeqkF4CezGS6OV0wFrk6YOBISGTEjVkqpy4c4VRqzr9MmTkPCkppOfvjim+HejYmxiUmBQoD8inc0iqtzM3jXYwIzUKWD309CItaNVXLDYAVhRg6zWn6FClPx5cSJTBJ3Fcygbl2iFq8tciylDy+qF+cmJhPbJxM0Xym+knQBqwri9cMf/nAqN6gaEDF3gJlM59ChQ4kSp8Rx85ImsWLB+VU3z42cFZ3/9yX2vBS7jUGsoYSWG0kDg5kXJ9C9tEnUT5yd+hkzeNzePL0gpuXXeiJ2EyTmlMiaJFh79zdLZ4q/+s3ZYnoBwAzeFXMaxK1vns8ekFILKk6Uy6h2TFFr/tQriV6c9jtHR9Rf4JFHHtF+km+/eKZYc+lp8S8vnzcUsUHCwuZG0bG4mb2ARAJm9fwsNUHypG3r/UoZGhqK/TtkJnX69v8wV1zSeHra77BBAuqQk/SgFv+atLDQJjLPkXZQbVMAvBczi1iQHHUNpigpFLQ5SoM6xCnxpSZ7ls+ZFn8Ctz36CtfgpQg/2ywpYYrKxfrQhz4UaqcS1BB31xEn4cVJm533xBNPGDlZpBdg37uxs+cFCqkFmMGjQCUbxHdgvahSKdUorSRZC362dvKimhuYZbfOigzx4eFhY229+/JZ4t9ePSN+9tKEqK+rmxIo5EB9/12v4yJhC1Hr4bxE6cknnwycs2TT2jpYe1GKpeVu3R4d4pRPS2dH/OnX/zosXhmfNfU7lQPFKgZ2ilOUS0hsC0bD8kLGui07qGgUJm1unTZx2rt3r/ET7/3zeWL87PRgOFw7CBSzyNOLqoxpGza5dppdOt86EtRESM3+S8h/+va1zWLkzBkKVEa46aabxJYtW7S3U26Bsx/rMAMunVZx0iKpJnKdyrE0N0N8Ykn9tAC5EihmkacHtTOJ7oW+iBuh2sHu3buL7eHVr5Vm01Ka/fv303JSmAyIl/LRN8wR73jNuakFwgrsgUeBSo846SzWpkrlomKlOz1B1fb2K1C2LEROquWkRVJNpRJ48fXl80Wu7sINObHMhQKVfDDTh40sdYFqCJXED+LkJ+HTFutJY8wpH+TN9To/PAjPPPNMrDfkn67PiZHRkxSolIL8J11BZz/Ck6QyuxSnEp5++ulYbwgC5L1/Pv+CGTwKVPzA8nBvxw0XCgd+H2S/Nr/Z4zpI0oJfjW5dINWzIiAO4kgnKAUB8tveOEMMj1KgbEbFkFSBOaQH+AH5RDZmY9uE5usTqIJdmIC4FlmN23JS3Li42RGoxgtm8JRAMc3APpAe4Ndt2rNnDy9YPC6ddstJm/UUd1DcDWbwrsudLStQqGJAgbKP7u5uX+/jZgVVTBu95XkpTlHQc21OXDP3zAUpBoCJmvaB5Sh+4jpw7by2hSJaLafAXlcYcdImrXElY3px558tEPPECAUqIfh17Wg9eaMx5hRY9ayxnIANQXE3mMG7b+VFYuL0iYoCxXIrFCdaTVUJHOwLI07apNU2y0kJ1LfflhOjYyNl/58CZQ9+K1tSnIxbTSAf9A/C1nPSssGmbXEnBVIMkAPV9ctjorlpzgX/rwrW3XXda8VbL5nFXu5B2L3iECNyC4raLCCs5YS4E0rqKpCKoMqVlAqXn6zt0r8Jm3BZem28zlMXmtfUBTbL6kI21OscnTrOAIslly5dauXg2ouZul8eF5fPm+v5nq+seA03TagwiN2iEBYkYHoJwPvf//7AlSnd69/87EBcDSSKloIlNF4F88Kcpw6WLFmic6ffwFoTtqqaNondtWuXtYPrescq+utrmsXzx094vgebJvzjgRNUopiweUcTm4EoaRSmUP5ivcnG/GBj3MkNkjQhUEdOnPR8z1f3F5hNHhNJWsNmE5rjTaEyX8OKk7awPsQpzhIqfgWqe+nssstcFMwmj4cga+2ISz30Zs6H0otaimVrk1rbUgq8BOoLV8+oKFAqm/y5kXH2frp1VtPf36/VMDMtTtqk9qc//WkibigE6n2XTVQUKKQYfOAXLzLVgG6dtSC/SXMlglAfbqXlZHvcyc1fL8uJd7z2XEWBgmv3gYdedFy9EY4EunbWoTneFPrDG+NotBooPIecJ1tTCkr52xUXiU89dlQ89NKIuLjZO40AM3l/KJwWn3cELauiEcXOJ9XEB20ESSdwW1u6dmZRJV5sFNkdO3bo/PjQHlZdjQ3vdo42HWeEfJgvf/nLiRp8EKgHXxivmAcFkKiJhE3uj0fiBukDyG/SyEVxuHU1qWKaXDu3BfWeyxoq5kEBBMo/8IsjjEORtLt0oeNNUYiTtjODWxd3XXGdAqV2GGYcisTJwMCAVu2r5Y8barUKnWOTczTpOLNFixZFspzANKsXzhaz6s6Jnx8eEfNmzfR83+lzE+Lhw6fE4ZFx8U7nbwgxCWbourq6dDbxNef4Q1yWk1br6f7770/sjf/YVXOLmeRPF4bLlltxg4RNzOYxH4qYRHNuU7GJWv44CnHSZhcm1bVTIA/qq63zfAmUyofCZp6EmGD79u3WCpP1llPSrSclUNi0EwJ1ZrzyUhbkQ33q0VeKa/MI0Qlm6TQXl6vZaIlCnPJC41q7++67L/EdAQL17bctEK+eHC67aUIpqGpAN48k3KWr2WiJKtFGm2unEjKTDoLk3/vPF4vCyHExcqZ6CgHdPJJgl25IRLABb1TipFWGUXQrDaCiJgRq+OTxistdSt08lF9hdQMSmXI47pzG2k0gkpTzqMQpEqX0wuYCdGEE6qG/uFS8tmFUvDziL8epOJvHpE2SDKspEpcuSnHSaj2hvlPSA+NuFjU3iB+sukRcNuNM1WRNBZI2EYf6u98f4+gioUFuk+Z4U15EFIOOUpy0rh5MShkVv2BXFwgUssnzRwtVUw0U3/rdMdaIIuEtCEeYNJZHidRIqYv4ix10jhZdZ/3rX/+6mDWeNrBg+AfPjIp/N3+emNXor1AEFg1/8i3zxUfeOJcjjvhm+fLlulMIlttoOWl17UCaXDs3WI/3jT9bUMyFOjF22tffIECOfChaUcQvECXNwhSZS6dDnLS6dmnIefICuVDfue414vipE74D5WCywsGL3PGFVMVAIDzS8V+n4Qtqde3uvfdesXr16tR2oCewg/Cjr4hj443i0rlzRH2d/1uEOlHYN++K5gaORDINxJkuuugi3c0sERHO2uuodqZVntOS8+RFMdXgXa8Ti5rGfS15oRVFLLGaIk8n0mE5tUjrSRtpDYy7GT5zTnxp/7D43qERcfm8eWJuhdIrXlbU5/9jTlztiB0hmnfzBai90hflB+qw/zFP2abTtUPe05o1a1LdmZoa6opLXjArN/D0cPEx0jzDv9CgRtQ/Hzwp4BVCqEh26evr010nXInTaJQfqKuItdYrgYxx2zfejArUheq7/rXizOlR8dyxY77zoRTIi3r3rheKLh/JJgaEqU/UUI7XtDj16/iybsvpnnvuyUznggWFhM3FsyfEwaMFX5UN3KiSwFinxzV62QI1wjXXCQdaFv7rEqeC0JzzlOa0gnIgUA6BetelM4sCdfRU8GoFqHDwF44VxYA5raYIyesa6zrnnA85xyd0ffgxx8W58sorE7O3XRQgDtWxqLm49OVHzxwXY+NnxdyZM0VdgHQD1C3/1xdHxcPPnxKvnzdDXDGnkSM4pSAArrlGOMA0oBbTrE7zF9/nHK26Phwzdpi5yyJ7XxoTnXtfESPn6gIteymlY/Eccetb5jM3KoVAmBAM10ykuU2mLCeAKGyHTutp5cqVRQsqayxyLJ6b3zBHPORYQH8sjASezVP8YfhMcXsqWFSc1UsPSLq85ZZbxOjoqM5m4M5pSzzUveWs1sA4uOOOOzLbAeHePfSuS4szei+fHPG1kUI5ECRXs3qsvJkOkHSpufoA0BrQ0m05QbYvc46362oAZXyzaj0pbrisqRgwxz55L548JWY1NIqZjcFvLURq17OnxK9eHnPcvEbGoxJsNd100026rSa4crfobKDewLXSnjefZetJgXQDVNh884JG8azj7qKIXRgrCiAnCqkHKA/Mige0muIa1yaioLhKCIpfTetJv5u34fVzxTHHAtp7ZEQcGzstmhobxYyGcLcZ8SikHWAyEMtgZjXUceTTalJjOvKM8DjECbzoHJ06G4BArV+/nr1TunkrL5klfvLsiDgyMho6WO62pB7408li0JwiZTdf+9rXxIMPPqi7GRRWe0B3IyZ7mdZSKgAlSGFBkUmweBjpBkg7gAV1+by5oVMOFIhFIfWgY3EzL7CFVhMW+Bpw6bSlD8RhORXHitCYVkDr6UKQtLm+ZU7R3fuX50dEYbR2KwpB84cPnxIDh0bEvJn1rHqQPatJa/pAXJYTOOocOVpP5kERu42PvVp8jcqKoiWVSaupXWjKCI/TcgKzxWQ5FVpPhnldU8NUsPyXL49GYkW5LSmmH2TCakJBuS+YOifTlhOspoO0nuIFMSjs+PLMybNFK+p1c+fULFIKZJl/8s3zmW2eTqsp8oJyNllO2pMyaT1VB0tfbmxpFmPnJopWFLZGR07UbEeggiwiLgeK3GE5DBYWz2pgTCpFVlNeipMx4ljt+aRzbNItTlmrWBAUBMtVZvnuF8ZEYexMMS9qZn1DqOzyUl4eZeDclNVkIK8JbBYRbvtko1un6BWa856yXLEgKEg52Piro2KXXFc3b9ZM8bo5c8WMhugWEDBwrsnPMlN5AFbTEtPnFledjP26rSdULFiwYIFYsWIFe7APKwp1opQVdez0WXHMeRJjW6rZEcWiVOAcGedM5oxIMczUa4rFaorTcjJiPUGcHn/88eIr8W9F3fm7Y+KepyarZUYdMFdg4wZYUR+5ah5rSYWkvb3dRAnegrSaCqbPL85eod16GhsbE01NTZy5C2hFqeUve18+LV4dO1sMmJ85d07MmVl7wFwB6+k3r54uWlIIosPtu7iJIuUXiNLWrVtNNPU153gwjnOM267Wbj2BLOxzZ8KKanCE6eI5zeKi2bO1tIf0g4+8ca5458LZvPhVWL58uRga0u5pxWY1xW05GbGewNNPPy3WrVvHHh3SikI5ll87Vs6Lo+Pi5OkzYnhsrKZqB17AgkI9Kczw4bH5+nmNjEuVAQFwQztfx2Y12SBOUOQWobHOODhw4ABLqtSAyi7HGj2I1MjZc0VXDxsszG6cIRrqoxUQBM+xCQMqIRw8flZcnZsp5s+o540Qk6kDq1evNpE6kHeOWJ/oNjyWIE4HdTfC1IJoeMaxbr40VJhKOwBw9V7juHr1dfq6E1w+bMaQ9VQExJm6u7tNNGU0G9xGy0lZT+jVbTobYWpBNMB6QtqBCphjrd7ImTOicCra1INyLp87FWHhnMbMWVNIHTAUnsgLw9ngtlpOwMiaO6YWRAsC5n//1Alxx++OTf0OcahL58wRc2fN1N4+AudrHUsqKwF0Q6kDVlhNtlhOAA609ooFSC04cuSIWLNmDZUlAhAwv96xoFAzCqVY4PJhjd4x5zrDmoJQRR00d4N4lAqgY8v1JfNnpNaawmJ2rKEzAKYAb7HhnG2aCoHVhE04W0zcaOY+RY+72oFCx1KYSqjY1DsXNhUTPdMAguBIHYBbZ8JAE4bqNSVJnECnmMx90gqD43pRuVFw+6Zc6qYmcXFzszGRgjDB3UMAPenlWzZv3iy2bdtmoqlBKU5WYFtK7pAUKK2xJwTHkelM60kPcPU6rmx2xGlC/NZx94ou9dmz4uipU8XHIXKk6ur0PhcRNFe7GSfZ7UOipaH1cwDR9hdsOXcbM9zanGO37kYQFN+9ezczxw24egiY43XqiegI00XNs7WnH5QDC47h9t3gWFVJWNNnKBMc9AkLZuhstpxAXgpUi85GEBx/4oknWJROtws9p7EYML/SeX3CsWSQeoCtPlX6Af5twpJSoM4UEjyRkvCk833GHM/zijkNVmaiw5XbsWOHiaaQzrNaaN6HLg3iBPYIA8taWJTOHCjH8rGr5hZNdbh6qMIZp0gBzPYhd+ofnjxunVAh+G2oiByIdZlKktw6RY8JgWLuk3lKFxTb4O65QSAdbl+cM34Gc5rgqSyxsZ/YLE5GEjMB1irde++9VA3DIC8K8agH8ietFCmAmT4lVqZiVEh1MbhQHQ31U5yC0ykMpBYAiBNEipgHCZxf2l+YFjRXIoUUBJRoMZWCUAkE04tCdflsbTXRDe6kAmCatdvaL5JQjwIzd21079JPuZm9qftjOE+qGiiOB6vqBsf1i3L5DCwmWE6GMLKteJrFCeVU9ploiO6dPSIFS+oJmSNVKlILmmZFXja4ViBQk2IV3v0z7M6hjGa3zf0gCXVRkRSGuNPbdTeEuk/XXHONuOqqq6gQMYL0A9SPcqcfKJDMiVpSmOVrqKuPZBurKMDMn0pRQNInEkDBJU3+Zv8wO2eoTpMQ56sOjNrcD5JSZtBYcJzunX084Ax2uHvuNXsKLCyGu4c1fHEHz71AfOqtF88qWlZvc45yM4AGZ+eK3qOwNAieRHECHc6xk+4dRaqcSKkZvgWzmqyJS/kVq+9862+L6+cM0S9irnCZRnECRoLj4K677mL2eAJFqmj9WhqXKsdo/rfi0Jb/IcZPHjPRHKYAlwuLg+BJFqcWMRkcN+Lece1dskUKGedIQ7DZ5fvTZ95TFChDwDzblpT7m7SNwqD8mGd+j+6GuPbOftSSGLweGT1XTOp0c/bcOXHi9Oni8pjxcxNiZkNj5Jsx1MILvd3i+K9+Zqq5QWFJEbm0ihP4f2Iy/nSZ7oaw9o6lVeznqnkziouLUdccAlUqUli3d0qWbMEsHxwGWFVxMvLbR8Xz9/wvk01aVQ4ljW6dwljuE4B7x8XByQF5Uvc7Ll/psphpT+UYs88RXzpw63Wm4kzA+pymNImTkBd7i4mGEHeCQDG9IFl4rd0rBYFzFUQ38r2+/pfi+L8Zc+dQDGp5Eu9fkjenHzTl3qFy5lNPPcVdgxMGtrHCbsWIS2EzBlWqpZQzMjYFt+/0+Dkx07GkGuv1WFOv/uQ7xcMgq5PmzqVBnMAvneMTJhpC9jj3vUsmapeY266eVzbrXAHZQgZ6YXS0uOU63IrG+obIguiYlYPVZBC4c/cn9b6lYSN6Y+4dYPwpHVRaZOzl9tWSkoD40p8++1/EmSPP0p3LkDgBBMdbTTTE+FO6UHGpB587NW23GC8gUHNnzgocnzIcZxJSmIaSfG8aUtLHjLl3jD+lCxWXuvkNc8RV82d4unyK0+Pj0+JTeLpXW3z80j/3iKM//ye6cxkVJwT8hoWB5EyA+BPzn9IF4lIqqRP5Us4NntrWqhwqPoXdjd1C1dhQP60OOvKZDn/rr0yeyqCwbBeVrLt1CmNr7wB3Dk6/y4c0BORMeS2RqeT6NZ8dFX/65PUm85kStXYua+LUIgytvSu6BFx/lxl2HT7lCNVI8dUv576yXohnnzT5NWEx9aXlmtelsB8ZK60CMHMHC4oB8uxYU7ueOyXuOXCiojU1ce8WMfHoD01+tcSUQvFLQwr7zx+kBWVk9u7IkSPFY82aNRy5GQAB9GtfO3NabOrZk+PTkjshShM/udvk14IbZ92mmBSn8mBTzvWm3DtUL2CCZvZAOWH3TB848Pvfion/8z9Nf5V18qGcKupS3HeMLg4u2tUMkGfb5XvmmWK53eHhYZPNJnJRrx/qU9xXkIC22WSDGzZsKFpRJHtAkG6++WbTwjSYVmFKuzgBVP3rN9lBb7vtNtMdlFjA7bffbvrBhLSBrjRf0/oM9BvcwLypxtBBYUGR7HDHHXeI+++/P9X9muKk7wljdIr1kUceKVpQJP1AlL7+9a+n2iOIi4aM9CGjy1uUBcUZvHSDe3zjjTeabnZIpCyfKeviBFB7HDN4V5tq8OGHH+YOwikWpo6OjuJGGIa9ACxPGc3CNa7LWJ9C3hPSC1pMNQjrCSkGrAGVHjDhAWGKYWa2XUzO0GWC+oz1KxV/KpjuyMiBIRSmGtiaJWHKojgpn32z6Q4dQw4M0UAMKQMAwe/urF3rugz3s17n6DTZIBcJJxvMwMaQMjAk3blC1q53Q4b72oAwtHuLgouEkwtECflMMYUh8lm85g0Z73MPiMnyvk2mGoRLgPgTBSpZwhRT3tpNImNxJorTeTAl+zNhqP64W6CYA5UMkFAbU8Y/AuDfzvK1b2D3KyZoHpIunjGQA3XllVcyxcBi8BBZv3696VwmgAD4LVm//hSnSRB0bBGGCtQpdu3aRYGyWJiQMhDDDKvKAB/N+j2oYzechtENEqYa5UadVgFBQl2mGHLTEABvFwnfby4q6nkJprEujo4RU1If8RCmGJNmY+l/FKdkoGrkFOIYEBQoO4QppvuAfjfIu0C3rhpt0sUzCtfhxQtcuZiEqU+kvHAcLafoGIyjs3CZS3wgjykmYYqlr1Gckk2fiGGDQsQ6YpolyrQwxbAsBWSmNhPdOj1gg84O041yHV7qhSlVW4dTnOIBNaAQf2o13TAFKtXCxJQBilNkAnVQGNqkkwKVamECXXGEDJIGY07BnnTGy1bEmKmcWu6++24KEy2n1NEmYkgxoAUVHTFWGBCCKQO0nDQyGFfnogVFYaLlRPywyTl6aEFRmHyCwPdy3gVaTibYFlfcgBZUIoWpnXeBlpNpjNchpwWVKGHCBMoSkcH63xQnO8A+eK1xNEyBsl6YmMtEty5WYuuAdPEoTLScSDViyyKnBWWdMKkH1iDvBC0nG4ilDhQtKCuFiXWZKE7WEevmhxQoUdxXzgJh6uNQoFtnK63SxcvF0XhWXbyY18pRmGg50YLyY0Fde+21mSr5a4Ew9VGYKE5JEqjNcTWepZrklggTl6XQrUscnWIyUTMW0l6TnMJEy4kktPMqCwpbaqcJnBeFKf1wx18zLp7x7c4V2EobgzgtOwsrwcV27hQmihNJuECBNGx9bkksjcJEcaJA6RAoxKFWrFhBYQrHoOBuKRQnCpQe4A5h+6k1a9Yk5qKpBNMDBw7Efe9WO8couzHFiQKlcbAnRaCUMB05ciTuexZb7hrFiWROoHDccMMNoqmpyWphinlJDoUpJpjnFC+dIsY8KGDrchcLFvBSmChOFCgKFIWJXAiTMOOnT8Q8NQ33qb293YrlLrfffjuFidByogU1nbiXu1iQ9W3Fw4JQnChQlgiUWo6CPCwKE1Fwts4uYp/Fw3KXHTt2GMsmV8mVe/fupTARihMFqjomlrtYklxJYaI4kSQKlK7lLpYkV1KYKE4kpEANOMd654gtS1LHchcEvW+88caiC0lhIhSnZPKCc/wsboFSy11WrlxZczb53XffLT772c/acG1RqfQL7GL2wtm6ZBDrpgmKWpM1LUkVEIKbEVCcSPoEatGiReLee+8NFCjHjNyGDRtsqchJYUoIzBBPDohBLRExb3EN9w6BbL85Ser9FghTgcKULBhzShaoJfSAc7zHOS6L60sgkL1z586qM3mIVa1evbooUBYIE5ajPMguRIhectLFm4j7WL9+/cRLL710wXHXXXdN2PD9nOOodIkJIQbptUEAVq5cOXHgwIEpYfrc5z5nizDtozARknGBWrp06UR/f3/RkrJImHLsHoTEyyZLBIHCRAi5gE6KUvHoZVcgxD6wFu8ohYkQYiOtGRWoTt56QuynRcZdKEyEEOvIZUCgmMNESILpTakwHaQwEZJ8egRTBQghltIp0jMjR2EiJGW0iWTP5PXwFhKSXlplvIYzcoQQ60jSTN5RafERQjIkULbP5LGqACEZpltwRo4QYimdwq5AOdfIEUKmsGVN3ibeCkJIKXEGyiGMHbwFhJBKAmU6UM7ANyHEN6aqa8a+Fx8hJHnoLl7HjG9CSGhahZ44VCcvLSGkVuB27RSswUQIsZRuwcRKQoildIpwcSgmVhJCtBO0skEnLxkhxBRwz3YLltIlhFiKVwlg5i8RQmIHbps7DsX8JUKINag4FNfHEUIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCMkadWk9seuuu65FXFi7Ov/oo4/2Zf2mO9emzXlp47VJxL1CH26p9B7nvnUb/k45ObZWod84x34dfacxxfcVN3RLye8GnYMDcFKYeG2SwYYyD5JSjImTI0woKogSzP3OsUONM+f3G53XdkekChQnkjULAoMiVzJQMRCG8OoMiiFeJSMWE4Rps3Msc46N8h60y4cdyjN3JUacpAuxO8Sf5uUB9qATOh2wn10kcy7NWuGj9K/zXmX9DcACjPIJTqbA/eiHC+dcb4zprfL+dErBOur8fnNU195my6nF5Wu3yQ5YkK7HVna+VIsS7nevqBJr8XBXcfQ4n4F+spn9JFJy0lBwu5ytajw613xQ/jwYRWP1Cbw4m5zjoHMhWEg/ncLUIy3tlho/qlP2E+6bF73RoNjv8nLU/0X2MKhP6AWCSO2UZj9JjzD1yodPlP1kHx9kkQGLaIOMPQHE+RAU75DWrogy9henOLX7OLqkG+elxr18MqZKmHQ9bHplagmpAUd4BqUg7XSO7fLfanzid5ujbK8x5hP1A4Jvm2UMotwTsEcKGUmuMHVoFCZlQfWyn0QCDIYt8nrmxfldnbuinrBKRCqBDGquczrxzjIC1YanovOePPtNIoUpJ/zvEIwH2oB8YuPvYDUvE/428kQ/aQvwUCTeYxHGwmbptRR0jb2k5Tlt9uiI+N02dp1EAovJj8vVVSYLuV8KnEoMzFX5jA0iopkkEm18qRz1CbsYedUhS1jMrpJYNvp4z9ZKyyPkIFnnx3ri5U4OScwQ31/GegoVFJdP3I2y07Z4uBChE/pK1iC1lXmyD8ljR63uhithsbSdvDyXHVG5NPK8OsT5PJecx7Xrr2Tyy+tfzWrK+1k7hnNzPm+oSl9o8XFuLfLc1nqcm8pK3yPPb6iGfrG2jGCqe9UXsevsPqcWD5d5j+zveYpTvHGO3iqxijZ5bJFZr30B2+iWwlfJ1WiVR6fz/rx0XQYDttMmKicstsiB0CmT5LpqvHaY6t9S5bzUtUMy5DbhnTTrx5IJEmQdqPaggiCWExQpSj2ievwqV9I3cE03+xUpGfzvrXD9ip/tvG+DT2uwWj/f5KMflvb3fnlOsYpUfQaFCZ13n/AXRFWdsVeKja8O4Rz7fAzgciKy2287LmspSMJimzz3ZWE6upzu7wl4XpvkeeVCuuMDAdoq+Lyf5a5jkD5xwTWVou3ngbXT5/VrE/7iaJX6+e4Q/VDI67Av7jSdJFpO5QbWUACh2SnCZR8Xn5KVLBvXwshabiraWeC0s9mnxRSUXMhBuLOGmE2r/Pv2oO54QEuy38dAzJcRpt4I+iWsxGXO9+2q8CDZEuK61SJMuRrOJycfKu1xLapOlDjJwV9ugOwJcbMLsjPvcXXYnIwPdXrcWHTiJRU+v9ejQ+Hzi0lrMjaizkMtmrzA2nDes8crb8TllnpZD30lFoeKrbWEvO49Htcd54XFnxDtvBwUrXIQlrYFV6VbZ+0h6YYEsTw7IhImRae8b30eLqPJkEUugo9TKzGWx7FGMWmWUzmXIh8i+atfxnfKXfB+52Zsl0/6UqFpqRCz6PSwSC5oS/67X7a1w8PU75WWWsHDVWrxsCDL1dSB9bFNuh49ATt7myi/pASfua7kvIoBfhmzKBfT24gYlA2LcasIfC2o++a20LZEJBZ+3ego3bEW+Zndpu9RImJOrnhHOSsjaMo8ZiPWVRogsmN1VfDHy7pjHmLRVaWt4iD3eGp5xTE2elgx7VXa2iaCB8R7Pc7L8xrK33eVulA1uJSmHnReluigPApBr5lHRVYvhmQ7QyHHSUsA11GdU97HezfGcYMaYxQcP/GLFulmdXh0pG0Braa8V0ygzABTFkDpYFrlYTWVs2R8leyQrl5fmU68sfSJJdsqdy26fLaF5UCr/AwY6faEOi9ZQmN7GUttg4i54qZrKr/qg6z0XH1an+5VC37FeJ27L8vx0RPQCvJzTurBkne1VW1dI4yDDtP11OK0nHb7OHorxH82Vwsae1gXQdjjYdGUsrbckylgMHerV6eoJo5SdIO0dcjn+8qd11CAtsp15jYRP34EA/fvAsGX1qcfcd1Y4RpecO9LB768xu0iWAmSDT5FMF/SVpePdlbRrfOn/EtkJzHRVimtPjv7jiANyQ4z6KNTtNXaVo2DeCDgORXKWC5xV5LwJRgh/6/0PvkR420V3GO/+VMtovqER6Wk2GoPHOP3LInihItkTamUCt8jjAm8x0enaAnRscLGL3IRtDXk0/o0STXBKFSyDuUAryYarT77aH9EEwR+2tof8v+EqL34X2CSmiGOzrU7TOa2BnIenTtMh8OA2OI1kLzidJpW2nt1xt2yXneSqSaOQz7vVauPflqLYEQtTmtlvDGM+GRHnJwBVXXPvJI1XG1lOlhPmWnbOCy5MJ2bxGPp+hlkfu7fcAQiKESEZW0jEjBrsNqtg/UBy8g5EBjs87j5PTF/zShdlLDWFqndIgwqPH7wE0TmgyyJ4lQiVJhRKBfH6UhRCVbuFEJI3G5dSLyKzbWJdOxWmwSRjaLUrW9rAa693/idzAGrNp2+nQ8bipMO6ynvUbMnzkENt2pLjN+nxfA9iNKN3COqB43bhP+ZzxYfn+enDElUOT37RfWcqsj2efNBXgTP9aM4BRSDUnFakBILKExwXZc4FTysk9YIV6n7GShrA4hT1X4gM9dxbrkar+kqn3212nISk1Vcd+hceB01ScxzGvY5qGO1JELulbaqygDOewmGhvMaCiCgtTxoqtEZIKbo95pXFfxKbVaojlF63/yIeJvBa7k2SQM9c8XmNDFUa0eo0OEH3G6th0XTpum8BjW6PJWy4kvZ6eP6tfmweAZLr2klUazwf342/lTJldWsw9Yq60xzNfTBcm11BuyXLXENKopTROZyuae4R/XHSh2+3Pv7fQhG0FXjfl2JgRotGT9s9zmo9nm1Kwf3zgDn48dN3FJuIMu2NgZoy4/49pTrK3JBri9L1VWGpxq91ap24jrjPbKi6+64BlUjdSUS+sSFNXtUvaCqAVjZMct1+HKbKwyUcV+KncnPekM5uDprOK/iYBIB61t7rWrH72Qd7mrWHwbpQfletcxngfw7v65mv7LYfLaJgbzRJTR+98hzL/oe8HG91bn1ybDFYlF+0w0/Qu/n+/XI8+ovCZMsk222+rl3tJwSgBSQ7R7W0yYfwuRVUnVrmbb6PFyFnmomewALw8959foUpZyspLmzQn30zcL/tHubFMwtIlhhtdJdRfxWtGh1tec3prXVLb7CX+Bf1e/aIvzv5Vd6vwZFsJnNTa5zU+dX7npuiGNcUZyiY5uH3w/R2F0aV5CDFp1wn0eH2FphWc7WCk/63tJgPNqWYhKmrrTXeXXK8+rwEkIpSgddMZot5VwzGXzfrPHeFEo/X7a5VUc/KDNJstlgP/RT/iQosSQ6J9Gty3s83WK3npwb2OUhABCmNrlgdlA+tVqquAXdFdpCwbi1Hk/yTikc1QZrLuLzGpKf21rls8u6hPKchIi+dC6+U9kKobjGTpuLA7i51RgqV2NMuq79wkAVUHm/2kXtGxxcIFDC8K7a9SkRp1zIqfuoO0axhneVJ1e1WMKgz3hOlwi/LmuzCJD45/O8WkX5jUNLhWJ7JdEVwQusVesrFXcPkcui+iJoq19Uzp4Pc78KIkRGvs/7FfR75E2Pp8SJkzSZvWIuOQu+X7EYngie9VuQrly7z3K7quP2Be3sUgT2hDyvsIFRtLmkWoa5/P8l0uUq1DCY8PfL/SSMSoFaF3IAFl1GH3Xp1f3qD3ivBsNcB9f9qkV48/I6LokjIG7CrSuI6NPz8eQvN7vV4no6lWt3yMR3Vx1Rxpk2CO8a6Oo7DchYRSFEO11yB5eNFSwXdLIdJW3gvFYFuTbyb9dV2ca99NzQbn+QsjaynW65W7DaRtuPVTYozm+DHvRaqt1wOn221x+0Ldf1a5PXr8PjPPrF9JhjX5jQhat/bHXdr2qfM6juW1z71SnqBDFCuTKqOorESeHIlcRBChrPK1emwxd0dGyPtnQV2/MqfZuPsn5Y6f3SdS5V+kjk50UIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYSQ4Px/AQYAeGpRDl1A8RIAAAAASUVORK5CYII=">
88 <img class="logo" src="data:image/png;base64,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">
89 </div>
89 </div>
90 <div class="main">
90 <div class="main">
91 <h1>
91 <h1>
92 502 Bad Gateway | <span class="error_message">Backend server is unreachable</span>
92 502 Bad Gateway | <span class="error_message">Backend server is unreachable</span>
93 </h1>
93 </h1>
94 <div class="inner-column">
94 <div class="inner-column">
95 <h4>Possible Causes</h4>
95 <h4>Possible Causes</h4>
96 <ul>
96 <ul>
97 <li>The server is being restarted.</li>
97 <li>The server is being restarted.</li>
98 <li>The server is overloaded.</li>
98 <li>The server is overloaded.</li>
99 <li>The link may be incorrect.</li>
99 <li>The link may be incorrect.</li>
100 </ul>
100 </ul>
101 </div>
101 </div>
102 <div class="inner-column">
102 <div class="inner-column">
103 <h4>Support</h4>
103 <h4>Support</h4>
104 <p>For support, go to <a href="https://rhodecode.com/help/" target="_blank">Support</a>.
104 <p>For support, go to <a href="https://rhodecode.com/help/" target="_blank">Support</a>.
105 It may be useful to include your log file; see the log file locations <a href="https://rhodecode.com/r1/enterprise/docs/admin-system-overview/">here</a>.
105 It may be useful to include your log file; see the log file locations <a href="https://rhodecode.com/r1/enterprise/docs/admin-system-overview/">here</a>.
106 </p>
106 </p>
107 </div>
107 </div>
108 <div class="inner-column">
108 <div class="inner-column">
109 <h4>Documentation</h4>
109 <h4>Documentation</h4>
110 <p>For more information, see <a href="https://rhodecode.com/r1/enterprise/docs/">docs.rhodecode.com</a>.</p>
110 <p>For more information, see <a href="https://rhodecode.com/r1/enterprise/docs/">docs.rhodecode.com</a>.</p>
111 </div>
111 </div>
112 </div>
112 </div>
113 </body>
113 </body>
114 </html>
114 </html>
@@ -1,1245 +1,1247 b''
1 // Default styles
1 // Default styles
2
2
3 .diff-collapse {
3 .diff-collapse {
4 margin: @padding 0;
4 margin: @padding 0;
5 text-align: right;
5 text-align: right;
6 }
6 }
7
7
8 .diff-container {
8 .diff-container {
9 margin-bottom: @space;
9 margin-bottom: @space;
10
10
11 .diffblock {
11 .diffblock {
12 margin-bottom: @space;
12 margin-bottom: @space;
13 }
13 }
14
14
15 &.hidden {
15 &.hidden {
16 display: none;
16 display: none;
17 overflow: hidden;
17 overflow: hidden;
18 }
18 }
19 }
19 }
20
20
21
21
22 div.diffblock .sidebyside {
22 div.diffblock .sidebyside {
23 background: #ffffff;
23 background: #ffffff;
24 }
24 }
25
25
26 div.diffblock {
26 div.diffblock {
27 overflow-x: auto;
27 overflow-x: auto;
28 overflow-y: hidden;
28 overflow-y: hidden;
29 clear: both;
29 clear: both;
30 padding: 0px;
30 padding: 0px;
31 background: @grey6;
31 background: @grey6;
32 border: @border-thickness solid @grey5;
32 border: @border-thickness solid @grey5;
33 -webkit-border-radius: @border-radius @border-radius 0px 0px;
33 -webkit-border-radius: @border-radius @border-radius 0px 0px;
34 border-radius: @border-radius @border-radius 0px 0px;
34 border-radius: @border-radius @border-radius 0px 0px;
35
35
36
36
37 .comments-number {
37 .comments-number {
38 float: right;
38 float: right;
39 }
39 }
40
40
41 // BEGIN CODE-HEADER STYLES
41 // BEGIN CODE-HEADER STYLES
42
42
43 .code-header {
43 .code-header {
44 background: @grey6;
44 background: @grey6;
45 padding: 10px 0 10px 0;
45 padding: 10px 0 10px 0;
46 height: auto;
46 height: auto;
47 width: 100%;
47 width: 100%;
48
48
49 .hash {
49 .hash {
50 float: left;
50 float: left;
51 padding: 2px 0 0 2px;
51 padding: 2px 0 0 2px;
52 }
52 }
53
53
54 .date {
54 .date {
55 float: left;
55 float: left;
56 text-transform: uppercase;
56 text-transform: uppercase;
57 padding: 4px 0px 0px 2px;
57 padding: 4px 0px 0px 2px;
58 }
58 }
59
59
60 div {
60 div {
61 margin-left: 4px;
61 margin-left: 4px;
62 }
62 }
63
63
64 div.compare_header {
64 div.compare_header {
65 min-height: 40px;
65 min-height: 40px;
66 margin: 0;
66 margin: 0;
67 padding: 0 @padding;
67 padding: 0 @padding;
68
68
69 .drop-menu {
69 .drop-menu {
70 float:left;
70 float:left;
71 display: block;
71 display: block;
72 margin:0 0 @padding 0;
72 margin:0 0 @padding 0;
73 }
73 }
74
74
75 .compare-label {
75 .compare-label {
76 float: left;
76 float: left;
77 clear: both;
77 clear: both;
78 display: inline-block;
78 display: inline-block;
79 min-width: 5em;
79 min-width: 5em;
80 margin: 0;
80 margin: 0;
81 padding: @button-padding @button-padding @button-padding 0;
81 padding: @button-padding @button-padding @button-padding 0;
82 font-family: @text-semibold;
82 font-family: @text-semibold;
83 }
83 }
84
84
85 .compare-buttons {
85 .compare-buttons {
86 float: left;
86 float: left;
87 margin: 0;
87 margin: 0;
88 padding: 0 0 @padding;
88 padding: 0 0 @padding;
89
89
90 .btn {
90 .btn {
91 margin: 0 @padding 0 0;
91 margin: 0 @padding 0 0;
92 }
92 }
93 }
93 }
94 }
94 }
95
95
96 }
96 }
97
97
98 .parents {
98 .parents {
99 float: left;
99 float: left;
100 width: 100px;
100 width: 100px;
101 font-weight: 400;
101 font-weight: 400;
102 vertical-align: middle;
102 vertical-align: middle;
103 padding: 0px 2px 0px 2px;
103 padding: 0px 2px 0px 2px;
104 background-color: @grey6;
104 background-color: @grey6;
105
105
106 #parent_link {
106 #parent_link {
107 margin: 00px 2px;
107 margin: 00px 2px;
108
108
109 &.double {
109 &.double {
110 margin: 0px 2px;
110 margin: 0px 2px;
111 }
111 }
112
112
113 &.disabled{
113 &.disabled{
114 margin-right: @padding;
114 margin-right: @padding;
115 }
115 }
116 }
116 }
117 }
117 }
118
118
119 .children {
119 .children {
120 float: right;
120 float: right;
121 width: 100px;
121 width: 100px;
122 font-weight: 400;
122 font-weight: 400;
123 vertical-align: middle;
123 vertical-align: middle;
124 text-align: right;
124 text-align: right;
125 padding: 0px 2px 0px 2px;
125 padding: 0px 2px 0px 2px;
126 background-color: @grey6;
126 background-color: @grey6;
127
127
128 #child_link {
128 #child_link {
129 margin: 0px 2px;
129 margin: 0px 2px;
130
130
131 &.double {
131 &.double {
132 margin: 0px 2px;
132 margin: 0px 2px;
133 }
133 }
134
134
135 &.disabled{
135 &.disabled{
136 margin-right: @padding;
136 margin-right: @padding;
137 }
137 }
138 }
138 }
139 }
139 }
140
140
141 .changeset_header {
141 .changeset_header {
142 height: 16px;
142 height: 16px;
143
143
144 & > div{
144 & > div{
145 margin-right: @padding;
145 margin-right: @padding;
146 }
146 }
147 }
147 }
148
148
149 .changeset_file {
149 .changeset_file {
150 text-align: left;
150 text-align: left;
151 float: left;
151 float: left;
152 padding: 0;
152 padding: 0;
153
153
154 a{
154 a{
155 display: inline-block;
155 display: inline-block;
156 margin-right: 0.5em;
156 margin-right: 0.5em;
157 }
157 }
158
158
159 #selected_mode{
159 #selected_mode{
160 margin-left: 0;
160 margin-left: 0;
161 }
161 }
162 }
162 }
163
163
164 .diff-menu-wrapper {
164 .diff-menu-wrapper {
165 float: left;
165 float: left;
166 }
166 }
167
167
168 .diff-menu {
168 .diff-menu {
169 position: absolute;
169 position: absolute;
170 background: none repeat scroll 0 0 #FFFFFF;
170 background: none repeat scroll 0 0 #FFFFFF;
171 border-color: #003367 @grey3 @grey3;
171 border-color: #003367 @grey3 @grey3;
172 border-right: 1px solid @grey3;
172 border-right: 1px solid @grey3;
173 border-style: solid solid solid;
173 border-style: solid solid solid;
174 border-width: @border-thickness;
174 border-width: @border-thickness;
175 box-shadow: 2px 8px 4px rgba(0, 0, 0, 0.2);
175 box-shadow: 2px 8px 4px rgba(0, 0, 0, 0.2);
176 margin-top: 5px;
176 margin-top: 5px;
177 margin-left: 1px;
177 margin-left: 1px;
178 }
178 }
179
179
180 .diff-actions, .editor-actions {
180 .diff-actions, .editor-actions {
181 float: left;
181 float: left;
182
182
183 input{
183 input{
184 margin: 0 0.5em 0 0;
184 margin: 0 0.5em 0 0;
185 }
185 }
186 }
186 }
187
187
188 // END CODE-HEADER STYLES
188 // END CODE-HEADER STYLES
189
189
190 // BEGIN CODE-BODY STYLES
190 // BEGIN CODE-BODY STYLES
191
191
192 .code-body {
192 .code-body {
193 padding: 0;
193 padding: 0;
194 background-color: #ffffff;
194 background-color: #ffffff;
195 position: relative;
195 position: relative;
196 max-width: none;
196 max-width: none;
197 box-sizing: border-box;
197 box-sizing: border-box;
198 // TODO: johbo: Parent has overflow: auto, this forces the child here
198 // TODO: johbo: Parent has overflow: auto, this forces the child here
199 // to have the intended size and to scroll. Should be simplified.
199 // to have the intended size and to scroll. Should be simplified.
200 width: 100%;
200 width: 100%;
201 overflow-x: auto;
201 overflow-x: auto;
202 }
202 }
203
203
204 pre.raw {
204 pre.raw {
205 background: white;
205 background: white;
206 color: @grey1;
206 color: @grey1;
207 }
207 }
208 // END CODE-BODY STYLES
208 // END CODE-BODY STYLES
209
209
210 }
210 }
211
211
212
212
213 table.code-difftable {
213 table.code-difftable {
214 border-collapse: collapse;
214 border-collapse: collapse;
215 width: 99%;
215 width: 99%;
216 border-radius: 0px !important;
216 border-radius: 0px !important;
217
217
218 td {
218 td {
219 padding: 0 !important;
219 padding: 0 !important;
220 background: none !important;
220 background: none !important;
221 border: 0 !important;
221 border: 0 !important;
222 }
222 }
223
223
224 .context {
224 .context {
225 background: none repeat scroll 0 0 #DDE7EF;
225 background: none repeat scroll 0 0 #DDE7EF;
226 }
226 }
227
227
228 .add {
228 .add {
229 background: none repeat scroll 0 0 #DDFFDD;
229 background: none repeat scroll 0 0 #DDFFDD;
230
230
231 ins {
231 ins {
232 background: none repeat scroll 0 0 #AAFFAA;
232 background: none repeat scroll 0 0 #AAFFAA;
233 text-decoration: none;
233 text-decoration: none;
234 }
234 }
235 }
235 }
236
236
237 .del {
237 .del {
238 background: none repeat scroll 0 0 #FFDDDD;
238 background: none repeat scroll 0 0 #FFDDDD;
239
239
240 del {
240 del {
241 background: none repeat scroll 0 0 #FFAAAA;
241 background: none repeat scroll 0 0 #FFAAAA;
242 text-decoration: none;
242 text-decoration: none;
243 }
243 }
244 }
244 }
245
245
246 /** LINE NUMBERS **/
246 /** LINE NUMBERS **/
247 .lineno {
247 .lineno {
248 padding-left: 2px !important;
248 padding-left: 2px !important;
249 padding-right: 2px;
249 padding-right: 2px;
250 text-align: right;
250 text-align: right;
251 width: 32px;
251 width: 32px;
252 -moz-user-select: none;
252 -moz-user-select: none;
253 -webkit-user-select: none;
253 -webkit-user-select: none;
254 border-right: @border-thickness solid @grey5 !important;
254 border-right: @border-thickness solid @grey5 !important;
255 border-left: 0px solid #CCC !important;
255 border-left: 0px solid #CCC !important;
256 border-top: 0px solid #CCC !important;
256 border-top: 0px solid #CCC !important;
257 border-bottom: none !important;
257 border-bottom: none !important;
258
258
259 a {
259 a {
260 &:extend(pre);
260 &:extend(pre);
261 text-align: right;
261 text-align: right;
262 padding-right: 2px;
262 padding-right: 2px;
263 cursor: pointer;
263 cursor: pointer;
264 display: block;
264 display: block;
265 width: 32px;
265 width: 32px;
266 }
266 }
267 }
267 }
268
268
269 .context {
269 .context {
270 cursor: auto;
270 cursor: auto;
271 &:extend(pre);
271 &:extend(pre);
272 }
272 }
273
273
274 .lineno-inline {
274 .lineno-inline {
275 background: none repeat scroll 0 0 #FFF !important;
275 background: none repeat scroll 0 0 #FFF !important;
276 padding-left: 2px;
276 padding-left: 2px;
277 padding-right: 2px;
277 padding-right: 2px;
278 text-align: right;
278 text-align: right;
279 width: 30px;
279 width: 30px;
280 -moz-user-select: none;
280 -moz-user-select: none;
281 -webkit-user-select: none;
281 -webkit-user-select: none;
282 }
282 }
283
283
284 /** CODE **/
284 /** CODE **/
285 .code {
285 .code {
286 display: block;
286 display: block;
287 width: 100%;
287 width: 100%;
288
288
289 td {
289 td {
290 margin: 0;
290 margin: 0;
291 padding: 0;
291 padding: 0;
292 }
292 }
293
293
294 pre {
294 pre {
295 margin: 0;
295 margin: 0;
296 padding: 0;
296 padding: 0;
297 margin-left: .5em;
297 margin-left: .5em;
298 }
298 }
299 }
299 }
300 }
300 }
301
301
302
302
303 // Comments
303 // Comments
304
304
305 div.comment:target {
305 div.comment:target {
306 border-left: 6px solid @comment-highlight-color !important;
306 border-left: 6px solid @comment-highlight-color !important;
307 padding-left: 3px;
307 padding-left: 3px;
308 margin-left: -9px;
308 margin-left: -9px;
309 }
309 }
310
310
311 //TODO: anderson: can't get an absolute number out of anything, so had to put the
311 //TODO: anderson: can't get an absolute number out of anything, so had to put the
312 //current values that might change. But to make it clear I put as a calculation
312 //current values that might change. But to make it clear I put as a calculation
313 @comment-max-width: 1065px;
313 @comment-max-width: 1065px;
314 @pr-extra-margin: 34px;
314 @pr-extra-margin: 34px;
315 @pr-border-spacing: 4px;
315 @pr-border-spacing: 4px;
316 @pr-comment-width: @comment-max-width - @pr-extra-margin - @pr-border-spacing;
316 @pr-comment-width: @comment-max-width - @pr-extra-margin - @pr-border-spacing;
317
317
318 // Pull Request
318 // Pull Request
319 .cs_files .code-difftable {
319 .cs_files .code-difftable {
320 border: @border-thickness solid @grey5; //borders only on PRs
320 border: @border-thickness solid @grey5; //borders only on PRs
321
321
322 .comment-inline-form,
322 .comment-inline-form,
323 div.comment {
323 div.comment {
324 width: @pr-comment-width;
324 width: @pr-comment-width;
325 }
325 }
326 }
326 }
327
327
328 // Changeset
328 // Changeset
329 .code-difftable {
329 .code-difftable {
330 .comment-inline-form,
330 .comment-inline-form,
331 div.comment {
331 div.comment {
332 width: @comment-max-width;
332 width: @comment-max-width;
333 }
333 }
334 }
334 }
335
335
336 //Style page
336 //Style page
337 @style-extra-margin: @sidebar-width + (@sidebarpadding * 3) + @padding;
337 @style-extra-margin: @sidebar-width + (@sidebarpadding * 3) + @padding;
338 #style-page .code-difftable{
338 #style-page .code-difftable{
339 .comment-inline-form,
339 .comment-inline-form,
340 div.comment {
340 div.comment {
341 width: @comment-max-width - @style-extra-margin;
341 width: @comment-max-width - @style-extra-margin;
342 }
342 }
343 }
343 }
344
344
345 #context-bar > h2 {
345 #context-bar > h2 {
346 font-size: 20px;
346 font-size: 20px;
347 }
347 }
348
348
349 #context-bar > h2> a {
349 #context-bar > h2> a {
350 font-size: 20px;
350 font-size: 20px;
351 }
351 }
352 // end of defaults
352 // end of defaults
353
353
354 .file_diff_buttons {
354 .file_diff_buttons {
355 padding: 0 0 @padding;
355 padding: 0 0 @padding;
356
356
357 .drop-menu {
357 .drop-menu {
358 float: left;
358 float: left;
359 margin: 0 @padding 0 0;
359 margin: 0 @padding 0 0;
360 }
360 }
361 .btn {
361 .btn {
362 margin: 0 @padding 0 0;
362 margin: 0 @padding 0 0;
363 }
363 }
364 }
364 }
365
365
366 .code-body.textarea.editor {
366 .code-body.textarea.editor {
367 max-width: none;
367 max-width: none;
368 padding: 15px;
368 padding: 15px;
369 }
369 }
370
370
371 td.injected_diff{
371 td.injected_diff{
372 max-width: 1178px;
372 max-width: 1178px;
373 overflow-x: auto;
373 overflow-x: auto;
374 overflow-y: hidden;
374 overflow-y: hidden;
375
375
376 div.diff-container,
376 div.diff-container,
377 div.diffblock{
377 div.diffblock{
378 max-width: 100%;
378 max-width: 100%;
379 }
379 }
380
380
381 div.code-body {
381 div.code-body {
382 max-width: 1124px;
382 max-width: 1124px;
383 overflow-x: auto;
383 overflow-x: auto;
384 overflow-y: hidden;
384 overflow-y: hidden;
385 padding: 0;
385 padding: 0;
386 }
386 }
387 div.diffblock {
387 div.diffblock {
388 border: none;
388 border: none;
389 }
389 }
390
390
391 &.inline-form {
391 &.inline-form {
392 width: 99%
392 width: 99%
393 }
393 }
394 }
394 }
395
395
396
396
397 table.code-difftable {
397 table.code-difftable {
398 width: 100%;
398 width: 100%;
399 }
399 }
400
400
401 /** PYGMENTS COLORING **/
401 /** PYGMENTS COLORING **/
402 div.codeblock {
402 div.codeblock {
403
403
404 // TODO: johbo: Added interim to get rid of the margin around
404 // TODO: johbo: Added interim to get rid of the margin around
405 // Select2 widgets. This needs further cleanup.
405 // Select2 widgets. This needs further cleanup.
406 margin-top: @padding;
406 margin-top: @padding;
407
407
408 overflow: auto;
408 overflow: auto;
409 padding: 0px;
409 padding: 0px;
410 border: @border-thickness solid @grey5;
410 border: @border-thickness solid @grey5;
411 background: @grey6;
411 background: @grey6;
412 .border-radius(@border-radius);
412 .border-radius(@border-radius);
413
413
414 #remove_gist {
414 #remove_gist {
415 float: right;
415 float: right;
416 }
416 }
417
417
418 .gist_url {
418 .gist_url {
419 padding: 0px 0px 10px 0px;
419 padding: 0px 0px 10px 0px;
420 }
420 }
421
421
422 .author {
422 .author {
423 clear: both;
423 clear: both;
424 vertical-align: middle;
424 vertical-align: middle;
425 font-family: @text-bold;
425 font-family: @text-bold;
426 }
426 }
427
427
428 .btn-mini {
428 .btn-mini {
429 float: left;
429 float: left;
430 margin: 0 5px 0 0;
430 margin: 0 5px 0 0;
431 }
431 }
432
432
433 .code-header {
433 .code-header {
434 padding: @padding;
434 padding: @padding;
435 border-bottom: @border-thickness solid @grey5;
435 border-bottom: @border-thickness solid @grey5;
436
436
437 .rc-user {
437 .rc-user {
438 min-width: 0;
438 min-width: 0;
439 margin-right: .5em;
439 margin-right: .5em;
440 }
440 }
441
441
442 .stats {
442 .stats {
443 clear: both;
443 clear: both;
444 margin: 0 0 @padding 0;
444 margin: 0 0 @padding 0;
445 padding: 0;
445 padding: 0;
446 .left {
446 .left {
447 float: left;
447 float: left;
448 clear: left;
448 clear: left;
449 max-width: 75%;
449 max-width: 75%;
450 margin: 0 0 @padding 0;
450 margin: 0 0 @padding 0;
451
451
452 &.item {
452 &.item {
453 margin-right: @padding;
453 margin-right: @padding;
454 &.last { border-right: none; }
454 &.last { border-right: none; }
455 }
455 }
456 }
456 }
457 .buttons { float: right; }
457 .buttons { float: right; }
458 .author {
458 .author {
459 height: 25px; margin-left: 15px; font-weight: bold;
459 height: 25px; margin-left: 15px; font-weight: bold;
460 }
460 }
461 }
461 }
462
462
463 .commit {
463 .commit {
464 margin: 5px 0 0 26px;
464 margin: 5px 0 0 26px;
465 font-weight: normal;
465 font-weight: normal;
466 white-space: pre-wrap;
466 white-space: pre-wrap;
467 }
467 }
468 }
468 }
469
469
470 .message {
470 .message {
471 position: relative;
471 position: relative;
472 margin: @padding;
472 margin: @padding;
473
473
474 .codeblock-label {
474 .codeblock-label {
475 margin: 0 0 1em 0;
475 margin: 0 0 1em 0;
476 }
476 }
477 }
477 }
478
478
479 .code-body {
479 .code-body {
480 padding: @padding;
480 padding: @padding;
481 background-color: #ffffff;
481 background-color: #ffffff;
482 min-width: 100%;
482 min-width: 100%;
483 box-sizing: border-box;
483 box-sizing: border-box;
484 // TODO: johbo: Parent has overflow: auto, this forces the child here
484 // TODO: johbo: Parent has overflow: auto, this forces the child here
485 // to have the intended size and to scroll. Should be simplified.
485 // to have the intended size and to scroll. Should be simplified.
486 width: 100%;
486 width: 100%;
487 overflow-x: auto;
487 overflow-x: auto;
488
488
489 img.rendered-binary {
489 img.rendered-binary {
490 height: auto;
490 height: auto;
491 width: 100%;
491 width: 100%;
492 }
492 }
493 }
493 }
494 }
494 }
495
495
496 .code-highlighttable,
496 .code-highlighttable,
497 div.codeblock {
497 div.codeblock {
498
498
499 &.readme {
499 &.readme {
500 background-color: white;
500 background-color: white;
501 }
501 }
502
502
503 .markdown-block table {
503 .markdown-block table {
504 border-collapse: collapse;
504 border-collapse: collapse;
505
505
506 th,
506 th,
507 td {
507 td {
508 padding: .5em;
508 padding: .5em;
509 border: @border-thickness solid @border-default-color;
509 border: @border-thickness solid @border-default-color;
510 }
510 }
511 }
511 }
512
512
513 table {
513 table {
514 border: 0px;
514 border: 0px;
515 margin: 0;
515 margin: 0;
516 letter-spacing: normal;
516 letter-spacing: normal;
517
517
518
518
519 td {
519 td {
520 border: 0px;
520 border: 0px;
521 vertical-align: top;
521 vertical-align: top;
522 }
522 }
523 }
523 }
524 }
524 }
525
525
526 div.codeblock .code-header .search-path { padding: 0 0 0 10px; }
526 div.codeblock .code-header .search-path { padding: 0 0 0 10px; }
527 div.search-code-body {
527 div.search-code-body {
528 background-color: #ffffff; padding: 5px 0 5px 10px;
528 background-color: #ffffff; padding: 5px 0 5px 10px;
529 pre {
529 pre {
530 .match { background-color: #faffa6;}
530 .match { background-color: #faffa6;}
531 .break { display: block; width: 100%; background-color: #DDE7EF; color: #747474; }
531 .break { display: block; width: 100%; background-color: #DDE7EF; color: #747474; }
532 }
532 }
533 .code-highlighttable {
533 .code-highlighttable {
534 border-collapse: collapse;
534 border-collapse: collapse;
535
535
536 tr:hover {
536 tr:hover {
537 background: #fafafa;
537 background: #fafafa;
538 }
538 }
539 td.code {
539 td.code {
540 padding-left: 10px;
540 padding-left: 10px;
541 }
541 }
542 td.line {
542 td.line {
543 border-right: 1px solid #ccc !important;
543 border-right: 1px solid #ccc !important;
544 padding-right: 10px;
544 padding-right: 10px;
545 text-align: right;
545 text-align: right;
546 font-family: "Lucida Console",Monaco,monospace;
546 font-family: "Lucida Console",Monaco,monospace;
547 span {
547 span {
548 white-space: pre-wrap;
548 white-space: pre-wrap;
549 color: #666666;
549 color: #666666;
550 }
550 }
551 }
551 }
552 }
552 }
553 }
553 }
554
554
555 div.annotatediv { margin-left: 2px; margin-right: 4px; }
555 div.annotatediv { margin-left: 2px; margin-right: 4px; }
556 .code-highlight {
556 .code-highlight {
557 margin: 0; padding: 0; border-left: @border-thickness solid @grey5;
557 margin: 0; padding: 0; border-left: @border-thickness solid @grey5;
558 pre, .linenodiv pre { padding: 0 5px; margin: 0; }
558 pre, .linenodiv pre { padding: 0 5px; margin: 0; }
559 pre div:target {background-color: @comment-highlight-color !important;}
559 pre div:target {background-color: @comment-highlight-color !important;}
560 }
560 }
561
561
562 .linenos a { text-decoration: none; }
562 .linenos a { text-decoration: none; }
563
563
564 .CodeMirror-selected { background: @rchighlightblue; }
564 .CodeMirror-selected { background: @rchighlightblue; }
565 .CodeMirror-focused .CodeMirror-selected { background: @rchighlightblue; }
565 .CodeMirror-focused .CodeMirror-selected { background: @rchighlightblue; }
566 .CodeMirror ::selection { background: @rchighlightblue; }
566 .CodeMirror ::selection { background: @rchighlightblue; }
567 .CodeMirror ::-moz-selection { background: @rchighlightblue; }
567 .CodeMirror ::-moz-selection { background: @rchighlightblue; }
568
568
569 .code { display: block; border:0px !important; }
569 .code { display: block; border:0px !important; }
570 .code-highlight, /* TODO: dan: merge codehilite into code-highlight */
570 .code-highlight, /* TODO: dan: merge codehilite into code-highlight */
571 .codehilite {
571 .codehilite {
572 .hll { background-color: #ffffcc }
572 .hll { background-color: #ffffcc }
573 .c { color: #408080; font-style: italic } /* Comment */
573 .c { color: #408080; font-style: italic } /* Comment */
574 .err, .codehilite .err { border: none } /* Error */
574 .err, .codehilite .err { border: none } /* Error */
575 .k { color: #008000; font-weight: bold } /* Keyword */
575 .k { color: #008000; font-weight: bold } /* Keyword */
576 .o { color: #666666 } /* Operator */
576 .o { color: #666666 } /* Operator */
577 .cm { color: #408080; font-style: italic } /* Comment.Multiline */
577 .cm { color: #408080; font-style: italic } /* Comment.Multiline */
578 .cp { color: #BC7A00 } /* Comment.Preproc */
578 .cp { color: #BC7A00 } /* Comment.Preproc */
579 .c1 { color: #408080; font-style: italic } /* Comment.Single */
579 .c1 { color: #408080; font-style: italic } /* Comment.Single */
580 .cs { color: #408080; font-style: italic } /* Comment.Special */
580 .cs { color: #408080; font-style: italic } /* Comment.Special */
581 .gd { color: #A00000 } /* Generic.Deleted */
581 .gd { color: #A00000 } /* Generic.Deleted */
582 .ge { font-style: italic } /* Generic.Emph */
582 .ge { font-style: italic } /* Generic.Emph */
583 .gr { color: #FF0000 } /* Generic.Error */
583 .gr { color: #FF0000 } /* Generic.Error */
584 .gh { color: #000080; font-weight: bold } /* Generic.Heading */
584 .gh { color: #000080; font-weight: bold } /* Generic.Heading */
585 .gi { color: #00A000 } /* Generic.Inserted */
585 .gi { color: #00A000 } /* Generic.Inserted */
586 .go { color: #808080 } /* Generic.Output */
586 .go { color: #808080 } /* Generic.Output */
587 .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
587 .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
588 .gs { font-weight: bold } /* Generic.Strong */
588 .gs { font-weight: bold } /* Generic.Strong */
589 .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
589 .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
590 .gt { color: #0040D0 } /* Generic.Traceback */
590 .gt { color: #0040D0 } /* Generic.Traceback */
591 .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
591 .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
592 .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
592 .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
593 .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
593 .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
594 .kp { color: #008000 } /* Keyword.Pseudo */
594 .kp { color: #008000 } /* Keyword.Pseudo */
595 .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
595 .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
596 .kt { color: #B00040 } /* Keyword.Type */
596 .kt { color: #B00040 } /* Keyword.Type */
597 .m { color: #666666 } /* Literal.Number */
597 .m { color: #666666 } /* Literal.Number */
598 .s { color: #BA2121 } /* Literal.String */
598 .s { color: #BA2121 } /* Literal.String */
599 .na { color: #7D9029 } /* Name.Attribute */
599 .na { color: #7D9029 } /* Name.Attribute */
600 .nb { color: #008000 } /* Name.Builtin */
600 .nb { color: #008000 } /* Name.Builtin */
601 .nc { color: #0000FF; font-weight: bold } /* Name.Class */
601 .nc { color: #0000FF; font-weight: bold } /* Name.Class */
602 .no { color: #880000 } /* Name.Constant */
602 .no { color: #880000 } /* Name.Constant */
603 .nd { color: #AA22FF } /* Name.Decorator */
603 .nd { color: #AA22FF } /* Name.Decorator */
604 .ni { color: #999999; font-weight: bold } /* Name.Entity */
604 .ni { color: #999999; font-weight: bold } /* Name.Entity */
605 .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
605 .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
606 .nf { color: #0000FF } /* Name.Function */
606 .nf { color: #0000FF } /* Name.Function */
607 .nl { color: #A0A000 } /* Name.Label */
607 .nl { color: #A0A000 } /* Name.Label */
608 .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
608 .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
609 .nt { color: #008000; font-weight: bold } /* Name.Tag */
609 .nt { color: #008000; font-weight: bold } /* Name.Tag */
610 .nv { color: #19177C } /* Name.Variable */
610 .nv { color: #19177C } /* Name.Variable */
611 .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
611 .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
612 .w { color: #bbbbbb } /* Text.Whitespace */
612 .w { color: #bbbbbb } /* Text.Whitespace */
613 .mf { color: #666666 } /* Literal.Number.Float */
613 .mf { color: #666666 } /* Literal.Number.Float */
614 .mh { color: #666666 } /* Literal.Number.Hex */
614 .mh { color: #666666 } /* Literal.Number.Hex */
615 .mi { color: #666666 } /* Literal.Number.Integer */
615 .mi { color: #666666 } /* Literal.Number.Integer */
616 .mo { color: #666666 } /* Literal.Number.Oct */
616 .mo { color: #666666 } /* Literal.Number.Oct */
617 .sb { color: #BA2121 } /* Literal.String.Backtick */
617 .sb { color: #BA2121 } /* Literal.String.Backtick */
618 .sc { color: #BA2121 } /* Literal.String.Char */
618 .sc { color: #BA2121 } /* Literal.String.Char */
619 .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
619 .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
620 .s2 { color: #BA2121 } /* Literal.String.Double */
620 .s2 { color: #BA2121 } /* Literal.String.Double */
621 .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
621 .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
622 .sh { color: #BA2121 } /* Literal.String.Heredoc */
622 .sh { color: #BA2121 } /* Literal.String.Heredoc */
623 .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
623 .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
624 .sx { color: #008000 } /* Literal.String.Other */
624 .sx { color: #008000 } /* Literal.String.Other */
625 .sr { color: #BB6688 } /* Literal.String.Regex */
625 .sr { color: #BB6688 } /* Literal.String.Regex */
626 .s1 { color: #BA2121 } /* Literal.String.Single */
626 .s1 { color: #BA2121 } /* Literal.String.Single */
627 .ss { color: #19177C } /* Literal.String.Symbol */
627 .ss { color: #19177C } /* Literal.String.Symbol */
628 .bp { color: #008000 } /* Name.Builtin.Pseudo */
628 .bp { color: #008000 } /* Name.Builtin.Pseudo */
629 .vc { color: #19177C } /* Name.Variable.Class */
629 .vc { color: #19177C } /* Name.Variable.Class */
630 .vg { color: #19177C } /* Name.Variable.Global */
630 .vg { color: #19177C } /* Name.Variable.Global */
631 .vi { color: #19177C } /* Name.Variable.Instance */
631 .vi { color: #19177C } /* Name.Variable.Instance */
632 .il { color: #666666 } /* Literal.Number.Integer.Long */
632 .il { color: #666666 } /* Literal.Number.Integer.Long */
633 }
633 }
634
634
635 /* customized pre blocks for markdown/rst */
635 /* customized pre blocks for markdown/rst */
636 pre.literal-block, .codehilite pre{
636 pre.literal-block, .codehilite pre{
637 padding: @padding;
637 padding: @padding;
638 border: 1px solid @grey6;
638 border: 1px solid @grey6;
639 .border-radius(@border-radius);
639 .border-radius(@border-radius);
640 background-color: @grey7;
640 background-color: @grey7;
641 }
641 }
642
642
643
643
644 /* START NEW CODE BLOCK CSS */
644 /* START NEW CODE BLOCK CSS */
645
645
646 @cb-line-height: 18px;
646 @cb-line-height: 18px;
647 @cb-line-code-padding: 10px;
647 @cb-line-code-padding: 10px;
648 @cb-text-padding: 5px;
648 @cb-text-padding: 5px;
649
649
650 @pill-padding: 2px 7px;
650 @pill-padding: 2px 7px;
651 @pill-padding-small: 2px 2px 1px 2px;
651 @pill-padding-small: 2px 2px 1px 2px;
652
652
653 input.filediff-collapse-state {
653 input.filediff-collapse-state {
654 display: none;
654 display: none;
655
655
656 &:checked + .filediff { /* file diff is collapsed */
656 &:checked + .filediff { /* file diff is collapsed */
657 .cb {
657 .cb {
658 display: none
658 display: none
659 }
659 }
660 .filediff-collapse-indicator {
660 .filediff-collapse-indicator {
661 width: 0;
661 width: 0;
662 height: 0;
662 height: 0;
663 border-style: solid;
663 border-style: solid;
664 border-width: 4.5px 0 4.5px 9.3px;
664 border-width: 4.5px 0 4.5px 9.3px;
665 border-color: transparent transparent transparent #aaa;
665 border-color: transparent transparent transparent #aaa;
666 margin: 6px 0px;
666 margin: 6px 0px;
667 }
667 }
668 .filediff-menu {
668 .filediff-menu {
669 display: none;
669 display: none;
670 }
670 }
671
671
672 }
672 }
673
673
674 &+ .filediff { /* file diff is expanded */
674 &+ .filediff { /* file diff is expanded */
675 .filediff-collapse-indicator {
675 .filediff-collapse-indicator {
676 width: 0;
676 width: 0;
677 height: 0;
677 height: 0;
678 border-style: solid;
678 border-style: solid;
679 border-width: 9.3px 4.5px 0 4.5px;
679 border-width: 9.3px 4.5px 0 4.5px;
680 border-color: #aaa transparent transparent transparent;
680 border-color: #aaa transparent transparent transparent;
681 margin: 6px 0px;
681 margin: 6px 0px;
682
682
683 }
683 }
684 .filediff-menu {
684 .filediff-menu {
685 display: block;
685 display: block;
686 }
686 }
687 margin: 10px 0;
687 margin: 10px 0;
688 &:nth-child(2) {
688 &:nth-child(2) {
689 margin: 0;
689 margin: 0;
690 }
690 }
691 }
691 }
692 }
692 }
693
693
694 .filediffs .anchor {
694 .filediffs .anchor {
695 display: block;
695 display: block;
696 height: 40px;
696 height: 40px;
697 margin-top: -40px;
697 margin-top: -40px;
698 visibility: hidden;
698 visibility: hidden;
699 }
699 }
700
700
701 .filediffs .anchor:nth-of-type(1) {
701 .filediffs .anchor:nth-of-type(1) {
702 display: block;
702 display: block;
703 height: 80px;
703 height: 80px;
704 margin-top: -80px;
704 margin-top: -80px;
705 visibility: hidden;
705 visibility: hidden;
706 }
706 }
707
707
708 .cs_files {
708 .cs_files {
709 clear: both;
709 clear: both;
710 }
710 }
711
711
712 #diff-file-sticky{
712 #diff-file-sticky{
713 will-change: min-height;
713 will-change: min-height;
714 }
714 }
715
715
716 .sidebar__inner{
716 .sidebar__inner{
717 transform: translate(0, 0); /* For browsers don't support translate3d. */
717 transform: translate(0, 0); /* For browsers don't support translate3d. */
718 transform: translate3d(0, 0, 0);
718 transform: translate3d(0, 0, 0);
719 will-change: position, transform;
719 will-change: position, transform;
720 height: 70px;
720 height: 70px;
721 z-index: 30;
721 z-index: 30;
722 background-color: #fff;
722 background-color: #fff;
723 padding: 5px 0px;
723 padding: 5px 0px;
724 }
724 }
725
725
726 .sidebar__bar {
726 .sidebar__bar {
727 padding: 5px 0px 0px 0px
727 padding: 5px 0px 0px 0px
728 }
728 }
729
729
730 .fpath-placeholder {
730 .fpath-placeholder {
731 clear: both;
731 clear: both;
732 visibility: hidden
732 visibility: hidden
733 }
733 }
734
734
735 .is-affixed {
735 .is-affixed {
736 .sidebar_inner_shadow {
736 .sidebar_inner_shadow {
737 position: fixed;
737 position: fixed;
738 top: 75px;
738 top: 75px;
739 right: -100%;
739 right: -100%;
740 left: -100%;
740 left: -100%;
741 z-index: 28;
741 z-index: 28;
742 display: block;
742 display: block;
743 height: 5px;
743 height: 5px;
744 content: "";
744 content: "";
745 background: linear-gradient(rgba(0, 0, 0, 0.075), rgba(0, 0, 0, 0.001)) repeat-x 0 0;
745 background: linear-gradient(rgba(0, 0, 0, 0.075), rgba(0, 0, 0, 0.001)) repeat-x 0 0;
746 border-top: 1px solid rgba(0, 0, 0, 0.15);
746 border-top: 1px solid rgba(0, 0, 0, 0.15);
747 }
747 }
748 .fpath-placeholder {
748 .fpath-placeholder {
749 visibility: visible !important;
749 visibility: visible !important;
750 }
750 }
751 }
751 }
752
752
753 .diffset-menu {
753 .diffset-menu {
754 margin-bottom: 20px;
754 margin-bottom: 20px;
755 }
755 }
756 .diffset {
756 .diffset {
757 margin: 20px auto;
757 margin: 20px auto;
758 .diffset-heading {
758 .diffset-heading {
759 border: 1px solid @grey5;
759 border: 1px solid @grey5;
760 margin-bottom: -1px;
760 margin-bottom: -1px;
761 // margin-top: 20px;
761 // margin-top: 20px;
762 h2 {
762 h2 {
763 margin: 0;
763 margin: 0;
764 line-height: 38px;
764 line-height: 38px;
765 padding-left: 10px;
765 padding-left: 10px;
766 }
766 }
767 .btn {
767 .btn {
768 margin: 0;
768 margin: 0;
769 }
769 }
770 background: @grey6;
770 background: @grey6;
771 display: block;
771 display: block;
772 padding: 5px;
772 padding: 5px;
773 }
773 }
774 .diffset-heading-warning {
774 .diffset-heading-warning {
775 background: @alert3-inner;
775 background: @alert3-inner;
776 border: 1px solid @alert3;
776 border: 1px solid @alert3;
777 }
777 }
778 &.diffset-comments-disabled {
778 &.diffset-comments-disabled {
779 .cb-comment-box-opener, .comment-inline-form, .cb-comment-add-button {
779 .cb-comment-box-opener, .comment-inline-form, .cb-comment-add-button {
780 display: none !important;
780 display: none !important;
781 }
781 }
782 }
782 }
783 }
783 }
784
784
785 .filelist {
785 .filelist {
786 .pill {
786 .pill {
787 display: block;
787 display: block;
788 float: left;
788 float: left;
789 padding: @pill-padding-small;
789 padding: @pill-padding-small;
790 }
790 }
791 }
791 }
792
792
793 .pill {
793 .pill {
794 display: block;
794 display: block;
795 float: left;
795 float: left;
796 padding: @pill-padding;
796 padding: @pill-padding;
797 }
797 }
798
798
799 .pill-group {
799 .pill-group {
800 .pill {
800 .pill {
801 opacity: .8;
801 opacity: .8;
802 margin-right: 3px;
802 margin-right: 3px;
803 font-size: 12px;
804 font-weight: normal;
803
805
804 &:first-child {
806 &:first-child {
805 border-radius: @border-radius 0 0 @border-radius;
807 border-radius: @border-radius 0 0 @border-radius;
806 }
808 }
807 &:last-child {
809 &:last-child {
808 border-radius: 0 @border-radius @border-radius 0;
810 border-radius: 0 @border-radius @border-radius 0;
809 }
811 }
810 &:only-child {
812 &:only-child {
811 border-radius: @border-radius;
813 border-radius: @border-radius;
812 margin-right: 0;
814 margin-right: 0;
813 }
815 }
814 }
816 }
815 }
817 }
816
818
817 /* Main comments*/
819 /* Main comments*/
818 #comments {
820 #comments {
819 .comment-selected {
821 .comment-selected {
820 border-left: 6px solid @comment-highlight-color;
822 border-left: 6px solid @comment-highlight-color;
821 padding-left: 3px;
823 padding-left: 3px;
822 margin-left: -9px;
824 margin-left: -9px;
823 }
825 }
824 }
826 }
825
827
826 .filediff {
828 .filediff {
827 border: 1px solid @grey5;
829 border: 1px solid @grey5;
828
830
829 /* START OVERRIDES */
831 /* START OVERRIDES */
830 .code-highlight {
832 .code-highlight {
831 border: none; // TODO: remove this border from the global
833 border: none; // TODO: remove this border from the global
832 // .code-highlight, it doesn't belong there
834 // .code-highlight, it doesn't belong there
833 }
835 }
834 label {
836 label {
835 margin: 0; // TODO: remove this margin definition from global label
837 margin: 0; // TODO: remove this margin definition from global label
836 // it doesn't belong there - if margin on labels
838 // it doesn't belong there - if margin on labels
837 // are needed for a form they should be defined
839 // are needed for a form they should be defined
838 // in the form's class
840 // in the form's class
839 }
841 }
840 /* END OVERRIDES */
842 /* END OVERRIDES */
841
843
842 * {
844 * {
843 box-sizing: border-box;
845 box-sizing: border-box;
844 }
846 }
845 .filediff-anchor {
847 .filediff-anchor {
846 visibility: hidden;
848 visibility: hidden;
847 }
849 }
848 &:hover {
850 &:hover {
849 .filediff-anchor {
851 .filediff-anchor {
850 visibility: visible;
852 visibility: visible;
851 }
853 }
852 }
854 }
853
855
854 .filediff-collapse-indicator {
856 .filediff-collapse-indicator {
855 border-style: solid;
857 border-style: solid;
856 float: left;
858 float: left;
857 margin: 4px 0px 0 0;
859 margin: 4px 0px 0 0;
858 cursor: pointer;
860 cursor: pointer;
859 }
861 }
860
862
861 .filediff-heading {
863 .filediff-heading {
862 background: @grey7;
864 background: @grey7;
863 cursor: pointer;
865 cursor: pointer;
864 display: block;
866 display: block;
865 padding: 5px 10px;
867 padding: 5px 10px;
866 }
868 }
867 .filediff-heading:after {
869 .filediff-heading:after {
868 content: "";
870 content: "";
869 display: table;
871 display: table;
870 clear: both;
872 clear: both;
871 }
873 }
872 .filediff-heading:hover {
874 .filediff-heading:hover {
873 background: #e1e9f4 !important;
875 background: #e1e9f4 !important;
874 }
876 }
875
877
876 .filediff-menu {
878 .filediff-menu {
877 float: right;
879 float: right;
878 text-align: right;
880 text-align: right;
879 padding: 5px 5px 5px 0px;
881 padding: 5px 5px 5px 0px;
880
882
881 &> a,
883 &> a,
882 &> span {
884 &> span {
883 padding: 1px;
885 padding: 1px;
884 }
886 }
885 }
887 }
886
888
887 .filediff-collapse-button, .filediff-expand-button {
889 .filediff-collapse-button, .filediff-expand-button {
888 cursor: pointer;
890 cursor: pointer;
889 }
891 }
890 .filediff-collapse-button {
892 .filediff-collapse-button {
891 display: inline;
893 display: inline;
892 }
894 }
893 .filediff-expand-button {
895 .filediff-expand-button {
894 display: none;
896 display: none;
895 }
897 }
896 .filediff-collapsed .filediff-collapse-button {
898 .filediff-collapsed .filediff-collapse-button {
897 display: none;
899 display: none;
898 }
900 }
899 .filediff-collapsed .filediff-expand-button {
901 .filediff-collapsed .filediff-expand-button {
900 display: inline;
902 display: inline;
901 }
903 }
902
904
903 /**** COMMENTS ****/
905 /**** COMMENTS ****/
904
906
905 .filediff-menu {
907 .filediff-menu {
906 .show-comment-button {
908 .show-comment-button {
907 display: none;
909 display: none;
908 }
910 }
909 }
911 }
910 &.hide-comments {
912 &.hide-comments {
911 .inline-comments {
913 .inline-comments {
912 display: none;
914 display: none;
913 }
915 }
914 .filediff-menu {
916 .filediff-menu {
915 .show-comment-button {
917 .show-comment-button {
916 display: inline;
918 display: inline;
917 }
919 }
918 .hide-comment-button {
920 .hide-comment-button {
919 display: none;
921 display: none;
920 }
922 }
921 }
923 }
922 }
924 }
923
925
924 .hide-line-comments {
926 .hide-line-comments {
925 .inline-comments {
927 .inline-comments {
926 display: none;
928 display: none;
927 }
929 }
928 }
930 }
929
931
930 /**** END COMMENTS ****/
932 /**** END COMMENTS ****/
931
933
932 }
934 }
933
935
934
936
935
937
936 .filediff, .filelist {
938 .filediff, .filelist {
937 .pill {
939 .pill {
938 &[op="name"] {
940 &[op="name"] {
939 background: none;
941 background: none;
940 opacity: 1;
942 opacity: 1;
941 color: white;
943 color: white;
942 }
944 }
943 &[op="limited"] {
945 &[op="limited"] {
944 background: @grey2;
946 background: @grey2;
945 color: white;
947 color: white;
946 }
948 }
947 &[op="binary"] {
949 &[op="binary"] {
948 background: @color7;
950 background: @color7;
949 color: white;
951 color: white;
950 }
952 }
951 &[op="modified"] {
953 &[op="modified"] {
952 background: @alert1;
954 background: @alert1;
953 color: white;
955 color: white;
954 }
956 }
955 &[op="renamed"] {
957 &[op="renamed"] {
956 background: @color4;
958 background: @color4;
957 color: white;
959 color: white;
958 }
960 }
959 &[op="copied"] {
961 &[op="copied"] {
960 background: @color4;
962 background: @color4;
961 color: white;
963 color: white;
962 }
964 }
963 &[op="mode"] {
965 &[op="mode"] {
964 background: @grey3;
966 background: @grey3;
965 color: white;
967 color: white;
966 }
968 }
967 &[op="symlink"] {
969 &[op="symlink"] {
968 background: @color8;
970 background: @color8;
969 color: white;
971 color: white;
970 }
972 }
971
973
972 &[op="added"] { /* added lines */
974 &[op="added"] { /* added lines */
973 background: @alert1;
975 background: @alert1;
974 color: white;
976 color: white;
975 }
977 }
976 &[op="deleted"] { /* deleted lines */
978 &[op="deleted"] { /* deleted lines */
977 background: @alert2;
979 background: @alert2;
978 color: white;
980 color: white;
979 }
981 }
980
982
981 &[op="created"] { /* created file */
983 &[op="created"] { /* created file */
982 background: @alert1;
984 background: @alert1;
983 color: white;
985 color: white;
984 }
986 }
985 &[op="removed"] { /* deleted file */
987 &[op="removed"] { /* deleted file */
986 background: @color5;
988 background: @color5;
987 color: white;
989 color: white;
988 }
990 }
989 }
991 }
990 }
992 }
991
993
992
994
993 .filediff-outdated {
995 .filediff-outdated {
994 padding: 8px 0;
996 padding: 8px 0;
995
997
996 .filediff-heading {
998 .filediff-heading {
997 opacity: .5;
999 opacity: .5;
998 }
1000 }
999 }
1001 }
1000
1002
1001 table.cb {
1003 table.cb {
1002 width: 100%;
1004 width: 100%;
1003 border-collapse: collapse;
1005 border-collapse: collapse;
1004
1006
1005 .cb-text {
1007 .cb-text {
1006 padding: @cb-text-padding;
1008 padding: @cb-text-padding;
1007 }
1009 }
1008 .cb-hunk {
1010 .cb-hunk {
1009 padding: @cb-text-padding;
1011 padding: @cb-text-padding;
1010 }
1012 }
1011 .cb-expand {
1013 .cb-expand {
1012 display: none;
1014 display: none;
1013 }
1015 }
1014 .cb-collapse {
1016 .cb-collapse {
1015 display: inline;
1017 display: inline;
1016 }
1018 }
1017 &.cb-collapsed {
1019 &.cb-collapsed {
1018 .cb-line {
1020 .cb-line {
1019 display: none;
1021 display: none;
1020 }
1022 }
1021 .cb-expand {
1023 .cb-expand {
1022 display: inline;
1024 display: inline;
1023 }
1025 }
1024 .cb-collapse {
1026 .cb-collapse {
1025 display: none;
1027 display: none;
1026 }
1028 }
1027 .cb-hunk {
1029 .cb-hunk {
1028 display: none;
1030 display: none;
1029 }
1031 }
1030 }
1032 }
1031
1033
1032 /* intentionally general selector since .cb-line-selected must override it
1034 /* intentionally general selector since .cb-line-selected must override it
1033 and they both use !important since the td itself may have a random color
1035 and they both use !important since the td itself may have a random color
1034 generated by annotation blocks. TLDR: if you change it, make sure
1036 generated by annotation blocks. TLDR: if you change it, make sure
1035 annotated block selection and line selection in file view still work */
1037 annotated block selection and line selection in file view still work */
1036 .cb-line-fresh .cb-content {
1038 .cb-line-fresh .cb-content {
1037 background: white !important;
1039 background: white !important;
1038 }
1040 }
1039 .cb-warning {
1041 .cb-warning {
1040 background: #fff4dd;
1042 background: #fff4dd;
1041 }
1043 }
1042
1044
1043 &.cb-diff-sideside {
1045 &.cb-diff-sideside {
1044 td {
1046 td {
1045 &.cb-content {
1047 &.cb-content {
1046 width: 50%;
1048 width: 50%;
1047 }
1049 }
1048 }
1050 }
1049 }
1051 }
1050
1052
1051 tr {
1053 tr {
1052 &.cb-annotate {
1054 &.cb-annotate {
1053 border-top: 1px solid #eee;
1055 border-top: 1px solid #eee;
1054 }
1056 }
1055
1057
1056 &.cb-comment-info {
1058 &.cb-comment-info {
1057 border-top: 1px solid #eee;
1059 border-top: 1px solid #eee;
1058 color: rgba(0, 0, 0, 0.3);
1060 color: rgba(0, 0, 0, 0.3);
1059 background: #edf2f9;
1061 background: #edf2f9;
1060
1062
1061 td {
1063 td {
1062
1064
1063 }
1065 }
1064 }
1066 }
1065
1067
1066 &.cb-hunk {
1068 &.cb-hunk {
1067 font-family: @font-family-monospace;
1069 font-family: @font-family-monospace;
1068 color: rgba(0, 0, 0, 0.3);
1070 color: rgba(0, 0, 0, 0.3);
1069
1071
1070 td {
1072 td {
1071 &:first-child {
1073 &:first-child {
1072 background: #edf2f9;
1074 background: #edf2f9;
1073 }
1075 }
1074 &:last-child {
1076 &:last-child {
1075 background: #f4f7fb;
1077 background: #f4f7fb;
1076 }
1078 }
1077 }
1079 }
1078 }
1080 }
1079 }
1081 }
1080
1082
1081
1083
1082 td {
1084 td {
1083 vertical-align: top;
1085 vertical-align: top;
1084 padding: 0;
1086 padding: 0;
1085
1087
1086 &.cb-content {
1088 &.cb-content {
1087 font-size: 12.35px;
1089 font-size: 12.35px;
1088
1090
1089 &.cb-line-selected .cb-code {
1091 &.cb-line-selected .cb-code {
1090 background: @comment-highlight-color !important;
1092 background: @comment-highlight-color !important;
1091 }
1093 }
1092
1094
1093 span.cb-code {
1095 span.cb-code {
1094 line-height: @cb-line-height;
1096 line-height: @cb-line-height;
1095 padding-left: @cb-line-code-padding;
1097 padding-left: @cb-line-code-padding;
1096 padding-right: @cb-line-code-padding;
1098 padding-right: @cb-line-code-padding;
1097 display: block;
1099 display: block;
1098 white-space: pre-wrap;
1100 white-space: pre-wrap;
1099 font-family: @font-family-monospace;
1101 font-family: @font-family-monospace;
1100 word-break: break-all;
1102 word-break: break-all;
1101 .nonl {
1103 .nonl {
1102 color: @color5;
1104 color: @color5;
1103 }
1105 }
1104 .cb-action {
1106 .cb-action {
1105 &:before {
1107 &:before {
1106 content: " ";
1108 content: " ";
1107 }
1109 }
1108 &.cb-deletion:before {
1110 &.cb-deletion:before {
1109 content: "- ";
1111 content: "- ";
1110 }
1112 }
1111 &.cb-addition:before {
1113 &.cb-addition:before {
1112 content: "+ ";
1114 content: "+ ";
1113 }
1115 }
1114 }
1116 }
1115 }
1117 }
1116
1118
1117 &> button.cb-comment-box-opener {
1119 &> button.cb-comment-box-opener {
1118
1120
1119 padding: 2px 2px 1px 3px;
1121 padding: 2px 2px 1px 3px;
1120 margin-left: -6px;
1122 margin-left: -6px;
1121 margin-top: -1px;
1123 margin-top: -1px;
1122
1124
1123 border-radius: @border-radius;
1125 border-radius: @border-radius;
1124 position: absolute;
1126 position: absolute;
1125 display: none;
1127 display: none;
1126 }
1128 }
1127 .cb-comment {
1129 .cb-comment {
1128 margin-top: 10px;
1130 margin-top: 10px;
1129 white-space: normal;
1131 white-space: normal;
1130 }
1132 }
1131 }
1133 }
1132 &:hover {
1134 &:hover {
1133 button.cb-comment-box-opener {
1135 button.cb-comment-box-opener {
1134 display: block;
1136 display: block;
1135 }
1137 }
1136 &+ td button.cb-comment-box-opener {
1138 &+ td button.cb-comment-box-opener {
1137 display: block
1139 display: block
1138 }
1140 }
1139 }
1141 }
1140
1142
1141 &.cb-data {
1143 &.cb-data {
1142 text-align: right;
1144 text-align: right;
1143 width: 30px;
1145 width: 30px;
1144 font-family: @font-family-monospace;
1146 font-family: @font-family-monospace;
1145
1147
1146 .icon-comment {
1148 .icon-comment {
1147 cursor: pointer;
1149 cursor: pointer;
1148 }
1150 }
1149 &.cb-line-selected {
1151 &.cb-line-selected {
1150 background: @comment-highlight-color !important;
1152 background: @comment-highlight-color !important;
1151 }
1153 }
1152 &.cb-line-selected > div {
1154 &.cb-line-selected > div {
1153 display: block;
1155 display: block;
1154 background: @comment-highlight-color !important;
1156 background: @comment-highlight-color !important;
1155 line-height: @cb-line-height;
1157 line-height: @cb-line-height;
1156 color: rgba(0, 0, 0, 0.3);
1158 color: rgba(0, 0, 0, 0.3);
1157 }
1159 }
1158 }
1160 }
1159
1161
1160 &.cb-lineno {
1162 &.cb-lineno {
1161 padding: 0;
1163 padding: 0;
1162 width: 50px;
1164 width: 50px;
1163 color: rgba(0, 0, 0, 0.3);
1165 color: rgba(0, 0, 0, 0.3);
1164 text-align: right;
1166 text-align: right;
1165 border-right: 1px solid #eee;
1167 border-right: 1px solid #eee;
1166 font-family: @font-family-monospace;
1168 font-family: @font-family-monospace;
1167 -webkit-user-select: none;
1169 -webkit-user-select: none;
1168 -moz-user-select: none;
1170 -moz-user-select: none;
1169 user-select: none;
1171 user-select: none;
1170
1172
1171 a::before {
1173 a::before {
1172 content: attr(data-line-no);
1174 content: attr(data-line-no);
1173 }
1175 }
1174 &.cb-line-selected {
1176 &.cb-line-selected {
1175 background: @comment-highlight-color !important;
1177 background: @comment-highlight-color !important;
1176 }
1178 }
1177
1179
1178 a {
1180 a {
1179 display: block;
1181 display: block;
1180 padding-right: @cb-line-code-padding;
1182 padding-right: @cb-line-code-padding;
1181 padding-left: @cb-line-code-padding;
1183 padding-left: @cb-line-code-padding;
1182 line-height: @cb-line-height;
1184 line-height: @cb-line-height;
1183 color: rgba(0, 0, 0, 0.3);
1185 color: rgba(0, 0, 0, 0.3);
1184 }
1186 }
1185 }
1187 }
1186
1188
1187 &.cb-empty {
1189 &.cb-empty {
1188 background: @grey7;
1190 background: @grey7;
1189 }
1191 }
1190
1192
1191 ins {
1193 ins {
1192 color: black;
1194 color: black;
1193 background: #a6f3a6;
1195 background: #a6f3a6;
1194 text-decoration: none;
1196 text-decoration: none;
1195 }
1197 }
1196 del {
1198 del {
1197 color: black;
1199 color: black;
1198 background: #f8cbcb;
1200 background: #f8cbcb;
1199 text-decoration: none;
1201 text-decoration: none;
1200 }
1202 }
1201 &.cb-addition {
1203 &.cb-addition {
1202 background: #ecffec;
1204 background: #ecffec;
1203
1205
1204 &.blob-lineno {
1206 &.blob-lineno {
1205 background: #ddffdd;
1207 background: #ddffdd;
1206 }
1208 }
1207 }
1209 }
1208 &.cb-deletion {
1210 &.cb-deletion {
1209 background: #ffecec;
1211 background: #ffecec;
1210
1212
1211 &.blob-lineno {
1213 &.blob-lineno {
1212 background: #ffdddd;
1214 background: #ffdddd;
1213 }
1215 }
1214 }
1216 }
1215 &.cb-annotate-message-spacer {
1217 &.cb-annotate-message-spacer {
1216 width:8px;
1218 width:8px;
1217 padding: 1px 0px 0px 3px;
1219 padding: 1px 0px 0px 3px;
1218 }
1220 }
1219 &.cb-annotate-info {
1221 &.cb-annotate-info {
1220 width: 320px;
1222 width: 320px;
1221 min-width: 320px;
1223 min-width: 320px;
1222 max-width: 320px;
1224 max-width: 320px;
1223 padding: 5px 2px;
1225 padding: 5px 2px;
1224 font-size: 13px;
1226 font-size: 13px;
1225
1227
1226 .cb-annotate-message {
1228 .cb-annotate-message {
1227 padding: 2px 0px 0px 0px;
1229 padding: 2px 0px 0px 0px;
1228 white-space: pre-line;
1230 white-space: pre-line;
1229 overflow: hidden;
1231 overflow: hidden;
1230 }
1232 }
1231 .rc-user {
1233 .rc-user {
1232 float: none;
1234 float: none;
1233 padding: 0 6px 0 17px;
1235 padding: 0 6px 0 17px;
1234 min-width: unset;
1236 min-width: unset;
1235 min-height: unset;
1237 min-height: unset;
1236 }
1238 }
1237 }
1239 }
1238
1240
1239 &.cb-annotate-revision {
1241 &.cb-annotate-revision {
1240 cursor: pointer;
1242 cursor: pointer;
1241 text-align: right;
1243 text-align: right;
1242 padding: 1px 3px 0px 3px;
1244 padding: 1px 3px 0px 3px;
1243 }
1245 }
1244 }
1246 }
1245 }
1247 }
@@ -1,2466 +1,2453 b''
1 //Primary CSS
1 //Primary CSS
2
2
3 //--- IMPORTS ------------------//
3 //--- IMPORTS ------------------//
4
4
5 @import 'helpers';
5 @import 'helpers';
6 @import 'mixins';
6 @import 'mixins';
7 @import 'rcicons';
7 @import 'rcicons';
8 @import 'fonts';
9 @import 'variables';
8 @import 'variables';
10 @import 'bootstrap-variables';
9 @import 'bootstrap-variables';
11 @import 'form-bootstrap';
10 @import 'form-bootstrap';
12 @import 'codemirror';
11 @import 'codemirror';
13 @import 'legacy_code_styles';
12 @import 'legacy_code_styles';
14 @import 'readme-box';
13 @import 'readme-box';
15 @import 'progress-bar';
14 @import 'progress-bar';
16
15
17 @import 'type';
16 @import 'type';
18 @import 'alerts';
17 @import 'alerts';
19 @import 'buttons';
18 @import 'buttons';
20 @import 'tags';
19 @import 'tags';
21 @import 'code-block';
20 @import 'code-block';
22 @import 'examples';
21 @import 'examples';
23 @import 'login';
22 @import 'login';
24 @import 'main-content';
23 @import 'main-content';
25 @import 'select2';
24 @import 'select2';
26 @import 'comments';
25 @import 'comments';
27 @import 'panels-bootstrap';
26 @import 'panels-bootstrap';
28 @import 'panels';
27 @import 'panels';
29 @import 'deform';
28 @import 'deform';
30
29
31 //--- BASE ------------------//
30 //--- BASE ------------------//
32 .noscript-error {
31 .noscript-error {
33 top: 0;
32 top: 0;
34 left: 0;
33 left: 0;
35 width: 100%;
34 width: 100%;
36 z-index: 101;
35 z-index: 101;
37 text-align: center;
36 text-align: center;
38 font-family: @text-semibold;
37 font-family: @text-semibold;
39 font-size: 120%;
38 font-size: 120%;
40 color: white;
39 color: white;
41 background-color: @alert2;
40 background-color: @alert2;
42 padding: 5px 0 5px 0;
41 padding: 5px 0 5px 0;
43 }
42 }
44
43
45 html {
44 html {
46 display: table;
45 display: table;
47 height: 100%;
46 height: 100%;
48 width: 100%;
47 width: 100%;
49 }
48 }
50
49
51 body {
50 body {
52 display: table-cell;
51 display: table-cell;
53 width: 100%;
52 width: 100%;
54 }
53 }
55
54
56 //--- LAYOUT ------------------//
55 //--- LAYOUT ------------------//
57
56
58 .hidden{
57 .hidden{
59 display: none !important;
58 display: none !important;
60 }
59 }
61
60
62 .box{
61 .box{
63 float: left;
62 float: left;
64 width: 100%;
63 width: 100%;
65 }
64 }
66
65
67 .browser-header {
66 .browser-header {
68 clear: both;
67 clear: both;
69 }
68 }
70 .main {
69 .main {
71 clear: both;
70 clear: both;
72 padding:0 0 @pagepadding;
71 padding:0 0 @pagepadding;
73 height: auto;
72 height: auto;
74
73
75 &:after { //clearfix
74 &:after { //clearfix
76 content:"";
75 content:"";
77 clear:both;
76 clear:both;
78 width:100%;
77 width:100%;
79 display:block;
78 display:block;
80 }
79 }
81 }
80 }
82
81
83 .action-link{
82 .action-link{
84 margin-left: @padding;
83 margin-left: @padding;
85 padding-left: @padding;
84 padding-left: @padding;
86 border-left: @border-thickness solid @border-default-color;
85 border-left: @border-thickness solid @border-default-color;
87 }
86 }
88
87
89 input + .action-link, .action-link.first{
88 input + .action-link, .action-link.first{
90 border-left: none;
89 border-left: none;
91 }
90 }
92
91
93 .action-link.last{
92 .action-link.last{
94 margin-right: @padding;
93 margin-right: @padding;
95 padding-right: @padding;
94 padding-right: @padding;
96 }
95 }
97
96
98 .action-link.active,
97 .action-link.active,
99 .action-link.active a{
98 .action-link.active a{
100 color: @grey4;
99 color: @grey4;
101 }
100 }
102
101
103 .action-link.disabled {
102 .action-link.disabled {
104 color: @grey4;
103 color: @grey4;
105 cursor: inherit;
104 cursor: inherit;
106 }
105 }
107
106
108 .clipboard-action {
107 .clipboard-action {
109 cursor: pointer;
108 cursor: pointer;
110 }
109 }
111
110
112 ul.simple-list{
111 ul.simple-list{
113 list-style: none;
112 list-style: none;
114 margin: 0;
113 margin: 0;
115 padding: 0;
114 padding: 0;
116 }
115 }
117
116
118 .main-content {
117 .main-content {
119 padding-bottom: @pagepadding;
118 padding-bottom: @pagepadding;
120 }
119 }
121
120
122 .wide-mode-wrapper {
121 .wide-mode-wrapper {
123 max-width:4000px !important;
122 max-width:4000px !important;
124 }
123 }
125
124
126 .wrapper {
125 .wrapper {
127 position: relative;
126 position: relative;
128 max-width: @wrapper-maxwidth;
127 max-width: @wrapper-maxwidth;
129 margin: 0 auto;
128 margin: 0 auto;
130 }
129 }
131
130
132 #content {
131 #content {
133 clear: both;
132 clear: both;
134 padding: 0 @contentpadding;
133 padding: 0 @contentpadding;
135 }
134 }
136
135
137 .advanced-settings-fields{
136 .advanced-settings-fields{
138 input{
137 input{
139 margin-left: @textmargin;
138 margin-left: @textmargin;
140 margin-right: @padding/2;
139 margin-right: @padding/2;
141 }
140 }
142 }
141 }
143
142
144 .cs_files_title {
143 .cs_files_title {
145 margin: @pagepadding 0 0;
144 margin: @pagepadding 0 0;
146 }
145 }
147
146
148 input.inline[type="file"] {
147 input.inline[type="file"] {
149 display: inline;
148 display: inline;
150 }
149 }
151
150
152 .error_page {
151 .error_page {
153 margin: 10% auto;
152 margin: 10% auto;
154
153
155 h1 {
154 h1 {
156 color: @grey2;
155 color: @grey2;
157 }
156 }
158
157
159 .alert {
158 .alert {
160 margin: @padding 0;
159 margin: @padding 0;
161 }
160 }
162
161
163 .error-branding {
162 .error-branding {
164 font-family: @text-semibold;
163 font-family: @text-semibold;
165 color: @grey4;
164 color: @grey4;
166 }
165 }
167
166
168 .error_message {
167 .error_message {
169 font-family: @text-regular;
168 font-family: @text-regular;
170 }
169 }
171
170
172 .sidebar {
171 .sidebar {
173 min-height: 275px;
172 min-height: 275px;
174 margin: 0;
173 margin: 0;
175 padding: 0 0 @sidebarpadding @sidebarpadding;
174 padding: 0 0 @sidebarpadding @sidebarpadding;
176 border: none;
175 border: none;
177 }
176 }
178
177
179 .main-content {
178 .main-content {
180 position: relative;
179 position: relative;
181 margin: 0 @sidebarpadding @sidebarpadding;
180 margin: 0 @sidebarpadding @sidebarpadding;
182 padding: 0 0 0 @sidebarpadding;
181 padding: 0 0 0 @sidebarpadding;
183 border-left: @border-thickness solid @grey5;
182 border-left: @border-thickness solid @grey5;
184
183
185 @media (max-width:767px) {
184 @media (max-width:767px) {
186 clear: both;
185 clear: both;
187 width: 100%;
186 width: 100%;
188 margin: 0;
187 margin: 0;
189 border: none;
188 border: none;
190 }
189 }
191 }
190 }
192
191
193 .inner-column {
192 .inner-column {
194 float: left;
193 float: left;
195 width: 29.75%;
194 width: 29.75%;
196 min-height: 150px;
195 min-height: 150px;
197 margin: @sidebarpadding 2% 0 0;
196 margin: @sidebarpadding 2% 0 0;
198 padding: 0 2% 0 0;
197 padding: 0 2% 0 0;
199 border-right: @border-thickness solid @grey5;
198 border-right: @border-thickness solid @grey5;
200
199
201 @media (max-width:767px) {
200 @media (max-width:767px) {
202 clear: both;
201 clear: both;
203 width: 100%;
202 width: 100%;
204 border: none;
203 border: none;
205 }
204 }
206
205
207 ul {
206 ul {
208 padding-left: 1.25em;
207 padding-left: 1.25em;
209 }
208 }
210
209
211 &:last-child {
210 &:last-child {
212 margin: @sidebarpadding 0 0;
211 margin: @sidebarpadding 0 0;
213 border: none;
212 border: none;
214 }
213 }
215
214
216 h4 {
215 h4 {
217 margin: 0 0 @padding;
216 margin: 0 0 @padding;
218 font-family: @text-semibold;
217 font-family: @text-semibold;
219 }
218 }
220 }
219 }
221 }
220 }
222 .error-page-logo {
221 .error-page-logo {
223 width: 130px;
222 width: 130px;
224 height: 160px;
223 height: 160px;
225 }
224 }
226
225
227 // HEADER
226 // HEADER
228 .header {
227 .header {
229
228
230 // TODO: johbo: Fix login pages, so that they work without a min-height
229 // TODO: johbo: Fix login pages, so that they work without a min-height
231 // for the header and then remove the min-height. I chose a smaller value
230 // for the header and then remove the min-height. I chose a smaller value
232 // intentionally here to avoid rendering issues in the main navigation.
231 // intentionally here to avoid rendering issues in the main navigation.
233 min-height: 49px;
232 min-height: 49px;
234
233
235 position: relative;
234 position: relative;
236 vertical-align: bottom;
235 vertical-align: bottom;
237 padding: 0 @header-padding;
236 padding: 0 @header-padding;
238 background-color: @grey2;
237 background-color: @grey2;
239 color: @grey5;
238 color: @grey5;
240
239
241 .title {
240 .title {
242 overflow: visible;
241 overflow: visible;
243 }
242 }
244
243
245 &:before,
244 &:before,
246 &:after {
245 &:after {
247 content: "";
246 content: "";
248 clear: both;
247 clear: both;
249 width: 100%;
248 width: 100%;
250 }
249 }
251
250
252 // TODO: johbo: Avoids breaking "Repositories" chooser
251 // TODO: johbo: Avoids breaking "Repositories" chooser
253 .select2-container .select2-choice .select2-arrow {
252 .select2-container .select2-choice .select2-arrow {
254 display: none;
253 display: none;
255 }
254 }
256 }
255 }
257
256
258 #header-inner {
257 #header-inner {
259 &.title {
258 &.title {
260 margin: 0;
259 margin: 0;
261 }
260 }
262 &:before,
261 &:before,
263 &:after {
262 &:after {
264 content: "";
263 content: "";
265 clear: both;
264 clear: both;
266 }
265 }
267 }
266 }
268
267
269 // Gists
268 // Gists
270 #files_data {
269 #files_data {
271 clear: both; //for firefox
270 clear: both; //for firefox
272 }
271 }
273 #gistid {
272 #gistid {
274 margin-right: @padding;
273 margin-right: @padding;
275 }
274 }
276
275
277 // Global Settings Editor
276 // Global Settings Editor
278 .textarea.editor {
277 .textarea.editor {
279 float: left;
278 float: left;
280 position: relative;
279 position: relative;
281 max-width: @texteditor-width;
280 max-width: @texteditor-width;
282
281
283 select {
282 select {
284 position: absolute;
283 position: absolute;
285 top:10px;
284 top:10px;
286 right:0;
285 right:0;
287 }
286 }
288
287
289 .CodeMirror {
288 .CodeMirror {
290 margin: 0;
289 margin: 0;
291 }
290 }
292
291
293 .help-block {
292 .help-block {
294 margin: 0 0 @padding;
293 margin: 0 0 @padding;
295 padding:.5em;
294 padding:.5em;
296 background-color: @grey6;
295 background-color: @grey6;
297 &.pre-formatting {
296 &.pre-formatting {
298 white-space: pre;
297 white-space: pre;
299 }
298 }
300 }
299 }
301 }
300 }
302
301
303 ul.auth_plugins {
302 ul.auth_plugins {
304 margin: @padding 0 @padding @legend-width;
303 margin: @padding 0 @padding @legend-width;
305 padding: 0;
304 padding: 0;
306
305
307 li {
306 li {
308 margin-bottom: @padding;
307 margin-bottom: @padding;
309 line-height: 1em;
308 line-height: 1em;
310 list-style-type: none;
309 list-style-type: none;
311
310
312 .auth_buttons .btn {
311 .auth_buttons .btn {
313 margin-right: @padding;
312 margin-right: @padding;
314 }
313 }
315
314
316 &:before { content: none; }
315 &:before { content: none; }
317 }
316 }
318 }
317 }
319
318
320
319
321 // My Account PR list
320 // My Account PR list
322
321
323 #show_closed {
322 #show_closed {
324 margin: 0 1em 0 0;
323 margin: 0 1em 0 0;
325 }
324 }
326
325
327 .pullrequestlist {
326 .pullrequestlist {
328 .closed {
327 .closed {
329 background-color: @grey6;
328 background-color: @grey6;
330 }
329 }
331 .td-status {
330 .td-status {
332 padding-left: .5em;
331 padding-left: .5em;
333 }
332 }
334 .log-container .truncate {
333 .log-container .truncate {
335 height: 2.75em;
334 height: 2.75em;
336 white-space: pre-line;
335 white-space: pre-line;
337 }
336 }
338 table.rctable .user {
337 table.rctable .user {
339 padding-left: 0;
338 padding-left: 0;
340 }
339 }
341 table.rctable {
340 table.rctable {
342 td.td-description,
341 td.td-description,
343 .rc-user {
342 .rc-user {
344 min-width: auto;
343 min-width: auto;
345 }
344 }
346 }
345 }
347 }
346 }
348
347
349 // Pull Requests
348 // Pull Requests
350
349
351 .pullrequests_section_head {
350 .pullrequests_section_head {
352 display: block;
351 display: block;
353 clear: both;
352 clear: both;
354 margin: @padding 0;
353 margin: @padding 0;
355 font-family: @text-bold;
354 font-family: @text-bold;
356 }
355 }
357
356
358 .pr-origininfo, .pr-targetinfo {
357 .pr-origininfo, .pr-targetinfo {
359 position: relative;
358 position: relative;
360
359
361 .tag {
360 .tag {
362 display: inline-block;
361 display: inline-block;
363 margin: 0 1em .5em 0;
362 margin: 0 1em .5em 0;
364 }
363 }
365
364
366 .clone-url {
365 .clone-url {
367 display: inline-block;
366 display: inline-block;
368 margin: 0 0 .5em 0;
367 margin: 0 0 .5em 0;
369 padding: 0;
368 padding: 0;
370 line-height: 1.2em;
369 line-height: 1.2em;
371 }
370 }
372 }
371 }
373
372
374 .pr-mergeinfo {
373 .pr-mergeinfo {
375 min-width: 95% !important;
374 min-width: 95% !important;
376 padding: 0 !important;
375 padding: 0 !important;
377 border: 0;
376 border: 0;
378 }
377 }
379 .pr-mergeinfo-copy {
378 .pr-mergeinfo-copy {
380 padding: 0 0;
379 padding: 0 0;
381 }
380 }
382
381
383 .pr-pullinfo {
382 .pr-pullinfo {
384 min-width: 95% !important;
383 min-width: 95% !important;
385 padding: 0 !important;
384 padding: 0 !important;
386 border: 0;
385 border: 0;
387 }
386 }
388 .pr-pullinfo-copy {
387 .pr-pullinfo-copy {
389 padding: 0 0;
388 padding: 0 0;
390 }
389 }
391
390
392
391
393 #pr-title-input {
392 #pr-title-input {
394 width: 72%;
393 width: 72%;
395 font-size: 1em;
394 font-size: 1em;
396 font-family: @text-bold;
395 font-family: @text-bold;
397 margin: 0;
396 margin: 0;
398 padding: 0 0 0 @padding/4;
397 padding: 0 0 0 @padding/4;
399 line-height: 1.7em;
398 line-height: 1.7em;
400 color: @text-color;
399 color: @text-color;
401 letter-spacing: .02em;
400 letter-spacing: .02em;
402 }
401 }
403
402
404 #pullrequest_title {
403 #pullrequest_title {
405 width: 100%;
404 width: 100%;
406 box-sizing: border-box;
405 box-sizing: border-box;
407 }
406 }
408
407
409 #pr_open_message {
408 #pr_open_message {
410 border: @border-thickness solid #fff;
409 border: @border-thickness solid #fff;
411 border-radius: @border-radius;
410 border-radius: @border-radius;
412 padding: @padding-large-vertical @padding-large-vertical @padding-large-vertical 0;
411 padding: @padding-large-vertical @padding-large-vertical @padding-large-vertical 0;
413 text-align: left;
412 text-align: left;
414 overflow: hidden;
413 overflow: hidden;
415 }
414 }
416
415
417 .pr-submit-button {
416 .pr-submit-button {
418 float: right;
417 float: right;
419 margin: 0 0 0 5px;
418 margin: 0 0 0 5px;
420 }
419 }
421
420
422 .pr-spacing-container {
421 .pr-spacing-container {
423 padding: 20px;
422 padding: 20px;
424 clear: both
423 clear: both
425 }
424 }
426
425
427 #pr-description-input {
426 #pr-description-input {
428 margin-bottom: 0;
427 margin-bottom: 0;
429 }
428 }
430
429
431 .pr-description-label {
430 .pr-description-label {
432 vertical-align: top;
431 vertical-align: top;
433 }
432 }
434
433
435 .perms_section_head {
434 .perms_section_head {
436 min-width: 625px;
435 min-width: 625px;
437
436
438 h2 {
437 h2 {
439 margin-bottom: 0;
438 margin-bottom: 0;
440 }
439 }
441
440
442 .label-checkbox {
441 .label-checkbox {
443 float: left;
442 float: left;
444 }
443 }
445
444
446 &.field {
445 &.field {
447 margin: @space 0 @padding;
446 margin: @space 0 @padding;
448 }
447 }
449
448
450 &:first-child.field {
449 &:first-child.field {
451 margin-top: 0;
450 margin-top: 0;
452
451
453 .label {
452 .label {
454 margin-top: 0;
453 margin-top: 0;
455 padding-top: 0;
454 padding-top: 0;
456 }
455 }
457
456
458 .radios {
457 .radios {
459 padding-top: 0;
458 padding-top: 0;
460 }
459 }
461 }
460 }
462
461
463 .radios {
462 .radios {
464 position: relative;
463 position: relative;
465 width: 505px;
464 width: 505px;
466 }
465 }
467 }
466 }
468
467
469 //--- MODULES ------------------//
468 //--- MODULES ------------------//
470
469
471
470
472 // Server Announcement
471 // Server Announcement
473 #server-announcement {
472 #server-announcement {
474 width: 95%;
473 width: 95%;
475 margin: @padding auto;
474 margin: @padding auto;
476 padding: @padding;
475 padding: @padding;
477 border-width: 2px;
476 border-width: 2px;
478 border-style: solid;
477 border-style: solid;
479 .border-radius(2px);
478 .border-radius(2px);
480 font-family: @text-bold;
479 font-family: @text-bold;
481
480
482 &.info { border-color: @alert4; background-color: @alert4-inner; }
481 &.info { border-color: @alert4; background-color: @alert4-inner; }
483 &.warning { border-color: @alert3; background-color: @alert3-inner; }
482 &.warning { border-color: @alert3; background-color: @alert3-inner; }
484 &.error { border-color: @alert2; background-color: @alert2-inner; }
483 &.error { border-color: @alert2; background-color: @alert2-inner; }
485 &.success { border-color: @alert1; background-color: @alert1-inner; }
484 &.success { border-color: @alert1; background-color: @alert1-inner; }
486 &.neutral { border-color: @grey3; background-color: @grey6; }
485 &.neutral { border-color: @grey3; background-color: @grey6; }
487 }
486 }
488
487
489 // Fixed Sidebar Column
488 // Fixed Sidebar Column
490 .sidebar-col-wrapper {
489 .sidebar-col-wrapper {
491 padding-left: @sidebar-all-width;
490 padding-left: @sidebar-all-width;
492
491
493 .sidebar {
492 .sidebar {
494 width: @sidebar-width;
493 width: @sidebar-width;
495 margin-left: -@sidebar-all-width;
494 margin-left: -@sidebar-all-width;
496 }
495 }
497 }
496 }
498
497
499 .sidebar-col-wrapper.scw-small {
498 .sidebar-col-wrapper.scw-small {
500 padding-left: @sidebar-small-all-width;
499 padding-left: @sidebar-small-all-width;
501
500
502 .sidebar {
501 .sidebar {
503 width: @sidebar-small-width;
502 width: @sidebar-small-width;
504 margin-left: -@sidebar-small-all-width;
503 margin-left: -@sidebar-small-all-width;
505 }
504 }
506 }
505 }
507
506
508
507
509 // FOOTER
508 // FOOTER
510 #footer {
509 #footer {
511 padding: 0;
510 padding: 0;
512 text-align: center;
511 text-align: center;
513 vertical-align: middle;
512 vertical-align: middle;
514 color: @grey2;
513 color: @grey2;
515 background-color: @grey6;
514 background-color: @grey6;
516
515
517 p {
516 p {
518 margin: 0;
517 margin: 0;
519 padding: 1em;
518 padding: 1em;
520 line-height: 1em;
519 line-height: 1em;
521 }
520 }
522
521
523 .server-instance { //server instance
522 .server-instance { //server instance
524 display: none;
523 display: none;
525 }
524 }
526
525
527 .title {
526 .title {
528 float: none;
527 float: none;
529 margin: 0 auto;
528 margin: 0 auto;
530 }
529 }
531 }
530 }
532
531
533 button.close {
532 button.close {
534 padding: 0;
533 padding: 0;
535 cursor: pointer;
534 cursor: pointer;
536 background: transparent;
535 background: transparent;
537 border: 0;
536 border: 0;
538 .box-shadow(none);
537 .box-shadow(none);
539 -webkit-appearance: none;
538 -webkit-appearance: none;
540 }
539 }
541
540
542 .close {
541 .close {
543 float: right;
542 float: right;
544 font-size: 21px;
543 font-size: 21px;
545 font-family: @text-bootstrap;
544 font-family: @text-bootstrap;
546 line-height: 1em;
545 line-height: 1em;
547 font-weight: bold;
546 font-weight: bold;
548 color: @grey2;
547 color: @grey2;
549
548
550 &:hover,
549 &:hover,
551 &:focus {
550 &:focus {
552 color: @grey1;
551 color: @grey1;
553 text-decoration: none;
552 text-decoration: none;
554 cursor: pointer;
553 cursor: pointer;
555 }
554 }
556 }
555 }
557
556
558 // GRID
557 // GRID
559 .sorting,
558 .sorting,
560 .sorting_desc,
559 .sorting_desc,
561 .sorting_asc {
560 .sorting_asc {
562 cursor: pointer;
561 cursor: pointer;
563 }
562 }
564 .sorting_desc:after {
563 .sorting_desc:after {
565 content: "\00A0\25B2";
564 content: "\00A0\25B2";
566 font-size: .75em;
565 font-size: .75em;
567 }
566 }
568 .sorting_asc:after {
567 .sorting_asc:after {
569 content: "\00A0\25BC";
568 content: "\00A0\25BC";
570 font-size: .68em;
569 font-size: .68em;
571 }
570 }
572
571
573
572
574 .user_auth_tokens {
573 .user_auth_tokens {
575
574
576 &.truncate {
575 &.truncate {
577 white-space: nowrap;
576 white-space: nowrap;
578 overflow: hidden;
577 overflow: hidden;
579 text-overflow: ellipsis;
578 text-overflow: ellipsis;
580 }
579 }
581
580
582 .fields .field .input {
581 .fields .field .input {
583 margin: 0;
582 margin: 0;
584 }
583 }
585
584
586 input#description {
585 input#description {
587 width: 100px;
586 width: 100px;
588 margin: 0;
587 margin: 0;
589 }
588 }
590
589
591 .drop-menu {
590 .drop-menu {
592 // TODO: johbo: Remove this, should work out of the box when
591 // TODO: johbo: Remove this, should work out of the box when
593 // having multiple inputs inline
592 // having multiple inputs inline
594 margin: 0 0 0 5px;
593 margin: 0 0 0 5px;
595 }
594 }
596 }
595 }
597 #user_list_table {
596 #user_list_table {
598 .closed {
597 .closed {
599 background-color: @grey6;
598 background-color: @grey6;
600 }
599 }
601 }
600 }
602
601
603
602
604 input {
603 input {
605 &.disabled {
604 &.disabled {
606 opacity: .5;
605 opacity: .5;
607 }
606 }
608 }
607 }
609
608
610 // remove extra padding in firefox
609 // remove extra padding in firefox
611 input::-moz-focus-inner { border:0; padding:0 }
610 input::-moz-focus-inner { border:0; padding:0 }
612
611
613 .adjacent input {
612 .adjacent input {
614 margin-bottom: @padding;
613 margin-bottom: @padding;
615 }
614 }
616
615
617 .permissions_boxes {
616 .permissions_boxes {
618 display: block;
617 display: block;
619 }
618 }
620
619
621 //TODO: lisa: this should be in tables
620 //TODO: lisa: this should be in tables
622 .show_more_col {
621 .show_more_col {
623 width: 20px;
622 width: 20px;
624 }
623 }
625
624
626 //FORMS
625 //FORMS
627
626
628 .medium-inline,
627 .medium-inline,
629 input#description.medium-inline {
628 input#description.medium-inline {
630 display: inline;
629 display: inline;
631 width: @medium-inline-input-width;
630 width: @medium-inline-input-width;
632 min-width: 100px;
631 min-width: 100px;
633 }
632 }
634
633
635 select {
634 select {
636 //reset
635 //reset
637 -webkit-appearance: none;
636 -webkit-appearance: none;
638 -moz-appearance: none;
637 -moz-appearance: none;
639
638
640 display: inline-block;
639 display: inline-block;
641 height: 28px;
640 height: 28px;
642 width: auto;
641 width: auto;
643 margin: 0 @padding @padding 0;
642 margin: 0 @padding @padding 0;
644 padding: 0 18px 0 8px;
643 padding: 0 18px 0 8px;
645 line-height:1em;
644 line-height:1em;
646 font-size: @basefontsize;
645 font-size: @basefontsize;
647 border: @border-thickness solid @rcblue;
646 border: @border-thickness solid @rcblue;
648 background:white url("../images/dt-arrow-dn.png") no-repeat 100% 50%;
647 background:white url("../images/dt-arrow-dn.png") no-repeat 100% 50%;
649 color: @rcblue;
648 color: @rcblue;
650
649
651 &:after {
650 &:after {
652 content: "\00A0\25BE";
651 content: "\00A0\25BE";
653 }
652 }
654
653
655 &:focus {
654 &:focus {
656 outline: none;
655 outline: none;
657 }
656 }
658 }
657 }
659
658
660 option {
659 option {
661 &:focus {
660 &:focus {
662 outline: none;
661 outline: none;
663 }
662 }
664 }
663 }
665
664
666 input,
665 input,
667 textarea {
666 textarea {
668 padding: @input-padding;
667 padding: @input-padding;
669 border: @input-border-thickness solid @border-highlight-color;
668 border: @input-border-thickness solid @border-highlight-color;
670 .border-radius (@border-radius);
669 .border-radius (@border-radius);
671 font-family: @text-light;
670 font-family: @text-light;
672 font-size: @basefontsize;
671 font-size: @basefontsize;
673
672
674 &.input-sm {
673 &.input-sm {
675 padding: 5px;
674 padding: 5px;
676 }
675 }
677
676
678 &#description {
677 &#description {
679 min-width: @input-description-minwidth;
678 min-width: @input-description-minwidth;
680 min-height: 1em;
679 min-height: 1em;
681 padding: 10px;
680 padding: 10px;
682 }
681 }
683 }
682 }
684
683
685 .field-sm {
684 .field-sm {
686 input,
685 input,
687 textarea {
686 textarea {
688 padding: 5px;
687 padding: 5px;
689 }
688 }
690 }
689 }
691
690
692 textarea {
691 textarea {
693 display: block;
692 display: block;
694 clear: both;
693 clear: both;
695 width: 100%;
694 width: 100%;
696 min-height: 100px;
695 min-height: 100px;
697 margin-bottom: @padding;
696 margin-bottom: @padding;
698 .box-sizing(border-box);
697 .box-sizing(border-box);
699 overflow: auto;
698 overflow: auto;
700 }
699 }
701
700
702 label {
701 label {
703 font-family: @text-light;
702 font-family: @text-light;
704 }
703 }
705
704
706 // GRAVATARS
705 // GRAVATARS
707 // centers gravatar on username to the right
706 // centers gravatar on username to the right
708
707
709 .gravatar {
708 .gravatar {
710 display: inline;
709 display: inline;
711 min-width: 16px;
710 min-width: 16px;
712 min-height: 16px;
711 min-height: 16px;
713 margin: -5px 0;
712 margin: -5px 0;
714 padding: 0;
713 padding: 0;
715 line-height: 1em;
714 line-height: 1em;
716 border: 1px solid @grey4;
715 border: 1px solid @grey4;
717 box-sizing: content-box;
716 box-sizing: content-box;
718
717
719 &.gravatar-large {
718 &.gravatar-large {
720 margin: -0.5em .25em -0.5em 0;
719 margin: -0.5em .25em -0.5em 0;
721 }
720 }
722
721
723 & + .user {
722 & + .user {
724 display: inline;
723 display: inline;
725 margin: 0;
724 margin: 0;
726 padding: 0 0 0 .17em;
725 padding: 0 0 0 .17em;
727 line-height: 1em;
726 line-height: 1em;
728 }
727 }
729 }
728 }
730
729
731 .user-inline-data {
730 .user-inline-data {
732 display: inline-block;
731 display: inline-block;
733 float: left;
732 float: left;
734 padding-left: .5em;
733 padding-left: .5em;
735 line-height: 1.3em;
734 line-height: 1.3em;
736 }
735 }
737
736
738 .rc-user { // gravatar + user wrapper
737 .rc-user { // gravatar + user wrapper
739 float: left;
738 float: left;
740 position: relative;
739 position: relative;
741 min-width: 100px;
740 min-width: 100px;
742 max-width: 200px;
741 max-width: 200px;
743 min-height: (@gravatar-size + @border-thickness * 2); // account for border
742 min-height: (@gravatar-size + @border-thickness * 2); // account for border
744 display: block;
743 display: block;
745 padding: 0 0 0 (@gravatar-size + @basefontsize/2 + @border-thickness * 2);
744 padding: 0 0 0 (@gravatar-size + @basefontsize/2 + @border-thickness * 2);
746
745
747
746
748 .gravatar {
747 .gravatar {
749 display: block;
748 display: block;
750 position: absolute;
749 position: absolute;
751 top: 0;
750 top: 0;
752 left: 0;
751 left: 0;
753 min-width: @gravatar-size;
752 min-width: @gravatar-size;
754 min-height: @gravatar-size;
753 min-height: @gravatar-size;
755 margin: 0;
754 margin: 0;
756 }
755 }
757
756
758 .user {
757 .user {
759 display: block;
758 display: block;
760 max-width: 175px;
759 max-width: 175px;
761 padding-top: 2px;
760 padding-top: 2px;
762 overflow: hidden;
761 overflow: hidden;
763 text-overflow: ellipsis;
762 text-overflow: ellipsis;
764 }
763 }
765 }
764 }
766
765
767 .gist-gravatar,
766 .gist-gravatar,
768 .journal_container {
767 .journal_container {
769 .gravatar-large {
768 .gravatar-large {
770 margin: 0 .5em -10px 0;
769 margin: 0 .5em -10px 0;
771 }
770 }
772 }
771 }
773
772
774
773
775 // ADMIN SETTINGS
774 // ADMIN SETTINGS
776
775
777 // Tag Patterns
776 // Tag Patterns
778 .tag_patterns {
777 .tag_patterns {
779 .tag_input {
778 .tag_input {
780 margin-bottom: @padding;
779 margin-bottom: @padding;
781 }
780 }
782 }
781 }
783
782
784 .locked_input {
783 .locked_input {
785 position: relative;
784 position: relative;
786
785
787 input {
786 input {
788 display: inline;
787 display: inline;
789 margin: 3px 5px 0px 0px;
788 margin: 3px 5px 0px 0px;
790 }
789 }
791
790
792 br {
791 br {
793 display: none;
792 display: none;
794 }
793 }
795
794
796 .error-message {
795 .error-message {
797 float: left;
796 float: left;
798 width: 100%;
797 width: 100%;
799 }
798 }
800
799
801 .lock_input_button {
800 .lock_input_button {
802 display: inline;
801 display: inline;
803 }
802 }
804
803
805 .help-block {
804 .help-block {
806 clear: both;
805 clear: both;
807 }
806 }
808 }
807 }
809
808
810 // Notifications
809 // Notifications
811
810
812 .notifications_buttons {
811 .notifications_buttons {
813 margin: 0 0 @space 0;
812 margin: 0 0 @space 0;
814 padding: 0;
813 padding: 0;
815
814
816 .btn {
815 .btn {
817 display: inline-block;
816 display: inline-block;
818 }
817 }
819 }
818 }
820
819
821 .notification-list {
820 .notification-list {
822
821
823 div {
822 div {
824 display: inline-block;
823 display: inline-block;
825 vertical-align: middle;
824 vertical-align: middle;
826 }
825 }
827
826
828 .container {
827 .container {
829 display: block;
828 display: block;
830 margin: 0 0 @padding 0;
829 margin: 0 0 @padding 0;
831 }
830 }
832
831
833 .delete-notifications {
832 .delete-notifications {
834 margin-left: @padding;
833 margin-left: @padding;
835 text-align: right;
834 text-align: right;
836 cursor: pointer;
835 cursor: pointer;
837 }
836 }
838
837
839 .read-notifications {
838 .read-notifications {
840 margin-left: @padding/2;
839 margin-left: @padding/2;
841 text-align: right;
840 text-align: right;
842 width: 35px;
841 width: 35px;
843 cursor: pointer;
842 cursor: pointer;
844 }
843 }
845
844
846 .icon-minus-sign {
845 .icon-minus-sign {
847 color: @alert2;
846 color: @alert2;
848 }
847 }
849
848
850 .icon-ok-sign {
849 .icon-ok-sign {
851 color: @alert1;
850 color: @alert1;
852 }
851 }
853 }
852 }
854
853
855 .user_settings {
854 .user_settings {
856 float: left;
855 float: left;
857 clear: both;
856 clear: both;
858 display: block;
857 display: block;
859 width: 100%;
858 width: 100%;
860
859
861 .gravatar_box {
860 .gravatar_box {
862 margin-bottom: @padding;
861 margin-bottom: @padding;
863
862
864 &:after {
863 &:after {
865 content: " ";
864 content: " ";
866 clear: both;
865 clear: both;
867 width: 100%;
866 width: 100%;
868 }
867 }
869 }
868 }
870
869
871 .fields .field {
870 .fields .field {
872 clear: both;
871 clear: both;
873 }
872 }
874 }
873 }
875
874
876 .advanced_settings {
875 .advanced_settings {
877 margin-bottom: @space;
876 margin-bottom: @space;
878
877
879 .help-block {
878 .help-block {
880 margin-left: 0;
879 margin-left: 0;
881 }
880 }
882
881
883 button + .help-block {
882 button + .help-block {
884 margin-top: @padding;
883 margin-top: @padding;
885 }
884 }
886 }
885 }
887
886
888 // admin settings radio buttons and labels
887 // admin settings radio buttons and labels
889 .label-2 {
888 .label-2 {
890 float: left;
889 float: left;
891 width: @label2-width;
890 width: @label2-width;
892
891
893 label {
892 label {
894 color: @grey1;
893 color: @grey1;
895 }
894 }
896 }
895 }
897 .checkboxes {
896 .checkboxes {
898 float: left;
897 float: left;
899 width: @checkboxes-width;
898 width: @checkboxes-width;
900 margin-bottom: @padding;
899 margin-bottom: @padding;
901
900
902 .checkbox {
901 .checkbox {
903 width: 100%;
902 width: 100%;
904
903
905 label {
904 label {
906 margin: 0;
905 margin: 0;
907 padding: 0;
906 padding: 0;
908 }
907 }
909 }
908 }
910
909
911 .checkbox + .checkbox {
910 .checkbox + .checkbox {
912 display: inline-block;
911 display: inline-block;
913 }
912 }
914
913
915 label {
914 label {
916 margin-right: 1em;
915 margin-right: 1em;
917 }
916 }
918 }
917 }
919
918
920 // CHANGELOG
919 // CHANGELOG
921 .container_header {
920 .container_header {
922 float: left;
921 float: left;
923 display: block;
922 display: block;
924 width: 100%;
923 width: 100%;
925 margin: @padding 0 @padding;
924 margin: @padding 0 @padding;
926
925
927 #filter_changelog {
926 #filter_changelog {
928 float: left;
927 float: left;
929 margin-right: @padding;
928 margin-right: @padding;
930 }
929 }
931
930
932 .breadcrumbs_light {
931 .breadcrumbs_light {
933 display: inline-block;
932 display: inline-block;
934 }
933 }
935 }
934 }
936
935
937 .info_box {
936 .info_box {
938 float: right;
937 float: right;
939 }
938 }
940
939
941
940
942 #graph_nodes {
941 #graph_nodes {
943 padding-top: 43px;
942 padding-top: 43px;
944 }
943 }
945
944
946 #graph_content{
945 #graph_content{
947
946
948 // adjust for table headers so that graph renders properly
947 // adjust for table headers so that graph renders properly
949 // #graph_nodes padding - table cell padding
948 // #graph_nodes padding - table cell padding
950 padding-top: (@space - (@basefontsize * 2.4));
949 padding-top: (@space - (@basefontsize * 2.4));
951
950
952 &.graph_full_width {
951 &.graph_full_width {
953 width: 100%;
952 width: 100%;
954 max-width: 100%;
953 max-width: 100%;
955 }
954 }
956 }
955 }
957
956
958 #graph {
957 #graph {
959 .flag_status {
958 .flag_status {
960 margin: 0;
959 margin: 0;
961 }
960 }
962
961
963 .pagination-left {
962 .pagination-left {
964 float: left;
963 float: left;
965 clear: both;
964 clear: both;
966 }
965 }
967
966
968 .log-container {
967 .log-container {
969 max-width: 345px;
968 max-width: 345px;
970
969
971 .message{
970 .message{
972 max-width: 340px;
971 max-width: 340px;
973 }
972 }
974 }
973 }
975
974
976 .graph-col-wrapper {
975 .graph-col-wrapper {
977 padding-left: 110px;
976 padding-left: 110px;
978
977
979 #graph_nodes {
978 #graph_nodes {
980 width: 100px;
979 width: 100px;
981 margin-left: -110px;
980 margin-left: -110px;
982 float: left;
981 float: left;
983 clear: left;
982 clear: left;
984 }
983 }
985 }
984 }
986
985
987 .load-more-commits {
986 .load-more-commits {
988 text-align: center;
987 text-align: center;
989 }
988 }
990 .load-more-commits:hover {
989 .load-more-commits:hover {
991 background-color: @grey7;
990 background-color: @grey7;
992 }
991 }
993 .load-more-commits {
992 .load-more-commits {
994 a {
993 a {
995 display: block;
994 display: block;
996 }
995 }
997 }
996 }
998 }
997 }
999
998
1000 #filter_changelog {
999 #filter_changelog {
1001 float: left;
1000 float: left;
1002 }
1001 }
1003
1002
1004
1003
1005 //--- THEME ------------------//
1004 //--- THEME ------------------//
1006
1005
1007 #logo {
1006 #logo {
1008 float: left;
1007 float: left;
1009 margin: 9px 0 0 0;
1008 margin: 9px 0 0 0;
1010
1009
1011 .header {
1010 .header {
1012 background-color: transparent;
1011 background-color: transparent;
1013 }
1012 }
1014
1013
1015 a {
1014 a {
1016 display: inline-block;
1015 display: inline-block;
1017 }
1016 }
1018
1017
1019 img {
1018 img {
1020 height:30px;
1019 height:30px;
1021 }
1020 }
1022 }
1021 }
1023
1022
1024 .logo-wrapper {
1023 .logo-wrapper {
1025 float:left;
1024 float:left;
1026 }
1025 }
1027
1026
1028 .branding{
1027 .branding{
1029 float: left;
1028 float: left;
1030 padding: 9px 2px;
1029 padding: 9px 2px;
1031 line-height: 1em;
1030 line-height: 1em;
1032 font-size: @navigation-fontsize;
1031 font-size: @navigation-fontsize;
1033 }
1032 }
1034
1033
1035 img {
1034 img {
1036 border: none;
1035 border: none;
1037 outline: none;
1036 outline: none;
1038 }
1037 }
1039 user-profile-header
1038 user-profile-header
1040 label {
1039 label {
1041
1040
1042 input[type="checkbox"] {
1041 input[type="checkbox"] {
1043 margin-right: 1em;
1042 margin-right: 1em;
1044 }
1043 }
1045 input[type="radio"] {
1044 input[type="radio"] {
1046 margin-right: 1em;
1045 margin-right: 1em;
1047 }
1046 }
1048 }
1047 }
1049
1048
1050 .flag_status {
1049 .flag_status {
1051 margin: 2px 8px 6px 2px;
1050 margin: 2px 8px 6px 2px;
1052 &.under_review {
1051 &.under_review {
1053 .circle(5px, @alert3);
1052 .circle(5px, @alert3);
1054 }
1053 }
1055 &.approved {
1054 &.approved {
1056 .circle(5px, @alert1);
1055 .circle(5px, @alert1);
1057 }
1056 }
1058 &.rejected,
1057 &.rejected,
1059 &.forced_closed{
1058 &.forced_closed{
1060 .circle(5px, @alert2);
1059 .circle(5px, @alert2);
1061 }
1060 }
1062 &.not_reviewed {
1061 &.not_reviewed {
1063 .circle(5px, @grey5);
1062 .circle(5px, @grey5);
1064 }
1063 }
1065 }
1064 }
1066
1065
1067 .flag_status_comment_box {
1066 .flag_status_comment_box {
1068 margin: 5px 6px 0px 2px;
1067 margin: 5px 6px 0px 2px;
1069 }
1068 }
1070 .test_pattern_preview {
1069 .test_pattern_preview {
1071 margin: @space 0;
1070 margin: @space 0;
1072
1071
1073 p {
1072 p {
1074 margin-bottom: 0;
1073 margin-bottom: 0;
1075 border-bottom: @border-thickness solid @border-default-color;
1074 border-bottom: @border-thickness solid @border-default-color;
1076 color: @grey3;
1075 color: @grey3;
1077 }
1076 }
1078
1077
1079 .btn {
1078 .btn {
1080 margin-bottom: @padding;
1079 margin-bottom: @padding;
1081 }
1080 }
1082 }
1081 }
1083 #test_pattern_result {
1082 #test_pattern_result {
1084 display: none;
1083 display: none;
1085 &:extend(pre);
1084 &:extend(pre);
1086 padding: .9em;
1085 padding: .9em;
1087 color: @grey3;
1086 color: @grey3;
1088 background-color: @grey7;
1087 background-color: @grey7;
1089 border-right: @border-thickness solid @border-default-color;
1088 border-right: @border-thickness solid @border-default-color;
1090 border-bottom: @border-thickness solid @border-default-color;
1089 border-bottom: @border-thickness solid @border-default-color;
1091 border-left: @border-thickness solid @border-default-color;
1090 border-left: @border-thickness solid @border-default-color;
1092 }
1091 }
1093
1092
1094 #repo_vcs_settings {
1093 #repo_vcs_settings {
1095 #inherit_overlay_vcs_default {
1094 #inherit_overlay_vcs_default {
1096 display: none;
1095 display: none;
1097 }
1096 }
1098 #inherit_overlay_vcs_custom {
1097 #inherit_overlay_vcs_custom {
1099 display: custom;
1098 display: custom;
1100 }
1099 }
1101 &.inherited {
1100 &.inherited {
1102 #inherit_overlay_vcs_default {
1101 #inherit_overlay_vcs_default {
1103 display: block;
1102 display: block;
1104 }
1103 }
1105 #inherit_overlay_vcs_custom {
1104 #inherit_overlay_vcs_custom {
1106 display: none;
1105 display: none;
1107 }
1106 }
1108 }
1107 }
1109 }
1108 }
1110
1109
1111 .issue-tracker-link {
1110 .issue-tracker-link {
1112 color: @rcblue;
1111 color: @rcblue;
1113 }
1112 }
1114
1113
1115 // Issue Tracker Table Show/Hide
1114 // Issue Tracker Table Show/Hide
1116 #repo_issue_tracker {
1115 #repo_issue_tracker {
1117 #inherit_overlay {
1116 #inherit_overlay {
1118 display: none;
1117 display: none;
1119 }
1118 }
1120 #custom_overlay {
1119 #custom_overlay {
1121 display: custom;
1120 display: custom;
1122 }
1121 }
1123 &.inherited {
1122 &.inherited {
1124 #inherit_overlay {
1123 #inherit_overlay {
1125 display: block;
1124 display: block;
1126 }
1125 }
1127 #custom_overlay {
1126 #custom_overlay {
1128 display: none;
1127 display: none;
1129 }
1128 }
1130 }
1129 }
1131 }
1130 }
1132 table.issuetracker {
1131 table.issuetracker {
1133 &.readonly {
1132 &.readonly {
1134 tr, td {
1133 tr, td {
1135 color: @grey3;
1134 color: @grey3;
1136 }
1135 }
1137 }
1136 }
1138 .edit {
1137 .edit {
1139 display: none;
1138 display: none;
1140 }
1139 }
1141 .editopen {
1140 .editopen {
1142 .edit {
1141 .edit {
1143 display: inline;
1142 display: inline;
1144 }
1143 }
1145 .entry {
1144 .entry {
1146 display: none;
1145 display: none;
1147 }
1146 }
1148 }
1147 }
1149 tr td.td-action {
1148 tr td.td-action {
1150 min-width: 117px;
1149 min-width: 117px;
1151 }
1150 }
1152 td input {
1151 td input {
1153 max-width: none;
1152 max-width: none;
1154 min-width: 30px;
1153 min-width: 30px;
1155 width: 80%;
1154 width: 80%;
1156 }
1155 }
1157 .issuetracker_pref input {
1156 .issuetracker_pref input {
1158 width: 40%;
1157 width: 40%;
1159 }
1158 }
1160 input.edit_issuetracker_update {
1159 input.edit_issuetracker_update {
1161 margin-right: 0;
1160 margin-right: 0;
1162 width: auto;
1161 width: auto;
1163 }
1162 }
1164 }
1163 }
1165
1164
1166 table.integrations {
1165 table.integrations {
1167 .td-icon {
1166 .td-icon {
1168 width: 20px;
1167 width: 20px;
1169 .integration-icon {
1168 .integration-icon {
1170 height: 20px;
1169 height: 20px;
1171 width: 20px;
1170 width: 20px;
1172 }
1171 }
1173 }
1172 }
1174 }
1173 }
1175
1174
1176 .integrations {
1175 .integrations {
1177 a.integration-box {
1176 a.integration-box {
1178 color: @text-color;
1177 color: @text-color;
1179 &:hover {
1178 &:hover {
1180 .panel {
1179 .panel {
1181 background: #fbfbfb;
1180 background: #fbfbfb;
1182 }
1181 }
1183 }
1182 }
1184 .integration-icon {
1183 .integration-icon {
1185 width: 30px;
1184 width: 30px;
1186 height: 30px;
1185 height: 30px;
1187 margin-right: 20px;
1186 margin-right: 20px;
1188 float: left;
1187 float: left;
1189 }
1188 }
1190
1189
1191 .panel-body {
1190 .panel-body {
1192 padding: 10px;
1191 padding: 10px;
1193 }
1192 }
1194 .panel {
1193 .panel {
1195 margin-bottom: 10px;
1194 margin-bottom: 10px;
1196 }
1195 }
1197 h2 {
1196 h2 {
1198 display: inline-block;
1197 display: inline-block;
1199 margin: 0;
1198 margin: 0;
1200 min-width: 140px;
1199 min-width: 140px;
1201 }
1200 }
1202 }
1201 }
1203 a.integration-box.dummy-integration {
1202 a.integration-box.dummy-integration {
1204 color: @grey4
1203 color: @grey4
1205 }
1204 }
1206 }
1205 }
1207
1206
1208 //Permissions Settings
1207 //Permissions Settings
1209 #add_perm {
1208 #add_perm {
1210 margin: 0 0 @padding;
1209 margin: 0 0 @padding;
1211 cursor: pointer;
1210 cursor: pointer;
1212 }
1211 }
1213
1212
1214 .perm_ac {
1213 .perm_ac {
1215 input {
1214 input {
1216 width: 95%;
1215 width: 95%;
1217 }
1216 }
1218 }
1217 }
1219
1218
1220 .autocomplete-suggestions {
1219 .autocomplete-suggestions {
1221 width: auto !important; // overrides autocomplete.js
1220 width: auto !important; // overrides autocomplete.js
1222 margin: 0;
1221 margin: 0;
1223 border: @border-thickness solid @rcblue;
1222 border: @border-thickness solid @rcblue;
1224 border-radius: @border-radius;
1223 border-radius: @border-radius;
1225 color: @rcblue;
1224 color: @rcblue;
1226 background-color: white;
1225 background-color: white;
1227 }
1226 }
1228 .autocomplete-selected {
1227 .autocomplete-selected {
1229 background: #F0F0F0;
1228 background: #F0F0F0;
1230 }
1229 }
1231 .ac-container-wrap {
1230 .ac-container-wrap {
1232 margin: 0;
1231 margin: 0;
1233 padding: 8px;
1232 padding: 8px;
1234 border-bottom: @border-thickness solid @rclightblue;
1233 border-bottom: @border-thickness solid @rclightblue;
1235 list-style-type: none;
1234 list-style-type: none;
1236 cursor: pointer;
1235 cursor: pointer;
1237
1236
1238 &:hover {
1237 &:hover {
1239 background-color: @rclightblue;
1238 background-color: @rclightblue;
1240 }
1239 }
1241
1240
1242 img {
1241 img {
1243 height: @gravatar-size;
1242 height: @gravatar-size;
1244 width: @gravatar-size;
1243 width: @gravatar-size;
1245 margin-right: 1em;
1244 margin-right: 1em;
1246 }
1245 }
1247
1246
1248 strong {
1247 strong {
1249 font-weight: normal;
1248 font-weight: normal;
1250 }
1249 }
1251 }
1250 }
1252
1251
1253 // Settings Dropdown
1252 // Settings Dropdown
1254 .user-menu .container {
1253 .user-menu .container {
1255 padding: 0 4px;
1254 padding: 0 4px;
1256 margin: 0;
1255 margin: 0;
1257 }
1256 }
1258
1257
1259 .user-menu .gravatar {
1258 .user-menu .gravatar {
1260 cursor: pointer;
1259 cursor: pointer;
1261 }
1260 }
1262
1261
1263 .codeblock {
1262 .codeblock {
1264 margin-bottom: @padding;
1263 margin-bottom: @padding;
1265 clear: both;
1264 clear: both;
1266
1265
1267 .stats{
1266 .stats{
1268 overflow: hidden;
1267 overflow: hidden;
1269 }
1268 }
1270
1269
1271 .message{
1270 .message{
1272 textarea{
1271 textarea{
1273 margin: 0;
1272 margin: 0;
1274 }
1273 }
1275 }
1274 }
1276
1275
1277 .code-header {
1276 .code-header {
1278 .stats {
1277 .stats {
1279 line-height: 2em;
1278 line-height: 2em;
1280
1279
1281 .revision_id {
1280 .revision_id {
1282 margin-left: 0;
1281 margin-left: 0;
1283 }
1282 }
1284 .buttons {
1283 .buttons {
1285 padding-right: 0;
1284 padding-right: 0;
1286 }
1285 }
1287 }
1286 }
1288
1287
1289 .item{
1288 .item{
1290 margin-right: 0.5em;
1289 margin-right: 0.5em;
1291 }
1290 }
1292 }
1291 }
1293
1292
1294 #editor_container{
1293 #editor_container{
1295 position: relative;
1294 position: relative;
1296 margin: @padding;
1295 margin: @padding;
1297 }
1296 }
1298 }
1297 }
1299
1298
1300 #file_history_container {
1299 #file_history_container {
1301 display: none;
1300 display: none;
1302 }
1301 }
1303
1302
1304 .file-history-inner {
1303 .file-history-inner {
1305 margin-bottom: 10px;
1304 margin-bottom: 10px;
1306 }
1305 }
1307
1306
1308 // Pull Requests
1307 // Pull Requests
1309 .summary-details {
1308 .summary-details {
1310 width: 72%;
1309 width: 72%;
1311 }
1310 }
1312 .pr-summary {
1311 .pr-summary {
1313 border-bottom: @border-thickness solid @grey5;
1312 border-bottom: @border-thickness solid @grey5;
1314 margin-bottom: @space;
1313 margin-bottom: @space;
1315 }
1314 }
1316 .reviewers-title {
1315 .reviewers-title {
1317 width: 25%;
1316 width: 25%;
1318 min-width: 200px;
1317 min-width: 200px;
1319 }
1318 }
1320 .reviewers {
1319 .reviewers {
1321 width: 25%;
1320 width: 25%;
1322 min-width: 200px;
1321 min-width: 200px;
1323 }
1322 }
1324 .reviewers ul li {
1323 .reviewers ul li {
1325 position: relative;
1324 position: relative;
1326 width: 100%;
1325 width: 100%;
1327 padding-bottom: 8px;
1326 padding-bottom: 8px;
1328 }
1327 }
1329
1328
1330 .reviewer_entry {
1329 .reviewer_entry {
1331 min-height: 55px;
1330 min-height: 55px;
1332 }
1331 }
1333
1332
1334 .reviewers_member {
1333 .reviewers_member {
1335 width: 100%;
1334 width: 100%;
1336 overflow: auto;
1335 overflow: auto;
1337 }
1336 }
1338 .reviewer_reason {
1337 .reviewer_reason {
1339 padding-left: 20px;
1338 padding-left: 20px;
1340 line-height: 1.5em;
1339 line-height: 1.5em;
1341 }
1340 }
1342 .reviewer_status {
1341 .reviewer_status {
1343 display: inline-block;
1342 display: inline-block;
1344 vertical-align: top;
1343 vertical-align: top;
1345 width: 25px;
1344 width: 25px;
1346 min-width: 25px;
1345 min-width: 25px;
1347 height: 1.2em;
1346 height: 1.2em;
1348 margin-top: 3px;
1347 margin-top: 3px;
1349 line-height: 1em;
1348 line-height: 1em;
1350 }
1349 }
1351
1350
1352 .reviewer_name {
1351 .reviewer_name {
1353 display: inline-block;
1352 display: inline-block;
1354 max-width: 83%;
1353 max-width: 83%;
1355 padding-right: 20px;
1354 padding-right: 20px;
1356 vertical-align: middle;
1355 vertical-align: middle;
1357 line-height: 1;
1356 line-height: 1;
1358
1357
1359 .rc-user {
1358 .rc-user {
1360 min-width: 0;
1359 min-width: 0;
1361 margin: -2px 1em 0 0;
1360 margin: -2px 1em 0 0;
1362 }
1361 }
1363
1362
1364 .reviewer {
1363 .reviewer {
1365 float: left;
1364 float: left;
1366 }
1365 }
1367 }
1366 }
1368
1367
1369 .reviewer_member_mandatory {
1368 .reviewer_member_mandatory {
1370 position: absolute;
1369 position: absolute;
1371 left: 15px;
1370 left: 15px;
1372 top: 8px;
1371 top: 8px;
1373 width: 16px;
1372 width: 16px;
1374 font-size: 11px;
1373 font-size: 11px;
1375 margin: 0;
1374 margin: 0;
1376 padding: 0;
1375 padding: 0;
1377 color: black;
1376 color: black;
1378 }
1377 }
1379
1378
1380 .reviewer_member_mandatory_remove,
1379 .reviewer_member_mandatory_remove,
1381 .reviewer_member_remove {
1380 .reviewer_member_remove {
1382 position: absolute;
1381 position: absolute;
1383 right: 0;
1382 right: 0;
1384 top: 0;
1383 top: 0;
1385 width: 16px;
1384 width: 16px;
1386 margin-bottom: 10px;
1385 margin-bottom: 10px;
1387 padding: 0;
1386 padding: 0;
1388 color: black;
1387 color: black;
1389 }
1388 }
1390
1389
1391 .reviewer_member_mandatory_remove {
1390 .reviewer_member_mandatory_remove {
1392 color: @grey4;
1391 color: @grey4;
1393 }
1392 }
1394
1393
1395 .reviewer_member_status {
1394 .reviewer_member_status {
1396 margin-top: 5px;
1395 margin-top: 5px;
1397 }
1396 }
1398 .pr-summary #summary{
1397 .pr-summary #summary{
1399 width: 100%;
1398 width: 100%;
1400 }
1399 }
1401 .pr-summary .action_button:hover {
1400 .pr-summary .action_button:hover {
1402 border: 0;
1401 border: 0;
1403 cursor: pointer;
1402 cursor: pointer;
1404 }
1403 }
1405 .pr-details-title {
1404 .pr-details-title {
1406 padding-bottom: 8px;
1405 padding-bottom: 8px;
1407 border-bottom: @border-thickness solid @grey5;
1406 border-bottom: @border-thickness solid @grey5;
1408
1407
1409 .action_button.disabled {
1408 .action_button.disabled {
1410 color: @grey4;
1409 color: @grey4;
1411 cursor: inherit;
1410 cursor: inherit;
1412 }
1411 }
1413 .action_button {
1412 .action_button {
1414 color: @rcblue;
1413 color: @rcblue;
1415 }
1414 }
1416 }
1415 }
1417 .pr-details-content {
1416 .pr-details-content {
1418 margin-top: @textmargin;
1417 margin-top: @textmargin;
1419 margin-bottom: @textmargin;
1418 margin-bottom: @textmargin;
1420 }
1419 }
1421
1420
1422 .pr-reviewer-rules {
1421 .pr-reviewer-rules {
1423 padding: 10px 0px 20px 0px;
1422 padding: 10px 0px 20px 0px;
1424 }
1423 }
1425
1424
1426 .group_members {
1425 .group_members {
1427 margin-top: 0;
1426 margin-top: 0;
1428 padding: 0;
1427 padding: 0;
1429 list-style: outside none none;
1428 list-style: outside none none;
1430
1429
1431 img {
1430 img {
1432 height: @gravatar-size;
1431 height: @gravatar-size;
1433 width: @gravatar-size;
1432 width: @gravatar-size;
1434 margin-right: .5em;
1433 margin-right: .5em;
1435 margin-left: 3px;
1434 margin-left: 3px;
1436 }
1435 }
1437
1436
1438 .to-delete {
1437 .to-delete {
1439 .user {
1438 .user {
1440 text-decoration: line-through;
1439 text-decoration: line-through;
1441 }
1440 }
1442 }
1441 }
1443 }
1442 }
1444
1443
1445 .compare_view_commits_title {
1444 .compare_view_commits_title {
1446 .disabled {
1445 .disabled {
1447 cursor: inherit;
1446 cursor: inherit;
1448 &:hover{
1447 &:hover{
1449 background-color: inherit;
1448 background-color: inherit;
1450 color: inherit;
1449 color: inherit;
1451 }
1450 }
1452 }
1451 }
1453 }
1452 }
1454
1453
1455 .subtitle-compare {
1454 .subtitle-compare {
1456 margin: -15px 0px 0px 0px;
1455 margin: -15px 0px 0px 0px;
1457 }
1456 }
1458
1457
1459 .comments-summary-td {
1458 .comments-summary-td {
1460 border-top: 1px dashed @grey5;
1459 border-top: 1px dashed @grey5;
1461 }
1460 }
1462
1461
1463 // new entry in group_members
1462 // new entry in group_members
1464 .td-author-new-entry {
1463 .td-author-new-entry {
1465 background-color: rgba(red(@alert1), green(@alert1), blue(@alert1), 0.3);
1464 background-color: rgba(red(@alert1), green(@alert1), blue(@alert1), 0.3);
1466 }
1465 }
1467
1466
1468 .usergroup_member_remove {
1467 .usergroup_member_remove {
1469 width: 16px;
1468 width: 16px;
1470 margin-bottom: 10px;
1469 margin-bottom: 10px;
1471 padding: 0;
1470 padding: 0;
1472 color: black !important;
1471 color: black !important;
1473 cursor: pointer;
1472 cursor: pointer;
1474 }
1473 }
1475
1474
1476 .reviewer_ac .ac-input {
1475 .reviewer_ac .ac-input {
1477 width: 92%;
1476 width: 92%;
1478 margin-bottom: 1em;
1477 margin-bottom: 1em;
1479 }
1478 }
1480
1479
1481 .compare_view_commits tr{
1480 .compare_view_commits tr{
1482 height: 20px;
1481 height: 20px;
1483 }
1482 }
1484 .compare_view_commits td {
1483 .compare_view_commits td {
1485 vertical-align: top;
1484 vertical-align: top;
1486 padding-top: 10px;
1485 padding-top: 10px;
1487 }
1486 }
1488 .compare_view_commits .author {
1487 .compare_view_commits .author {
1489 margin-left: 5px;
1488 margin-left: 5px;
1490 }
1489 }
1491
1490
1492 .compare_view_commits {
1491 .compare_view_commits {
1493 .color-a {
1492 .color-a {
1494 color: @alert1;
1493 color: @alert1;
1495 }
1494 }
1496
1495
1497 .color-c {
1496 .color-c {
1498 color: @color3;
1497 color: @color3;
1499 }
1498 }
1500
1499
1501 .color-r {
1500 .color-r {
1502 color: @color5;
1501 color: @color5;
1503 }
1502 }
1504
1503
1505 .color-a-bg {
1504 .color-a-bg {
1506 background-color: @alert1;
1505 background-color: @alert1;
1507 }
1506 }
1508
1507
1509 .color-c-bg {
1508 .color-c-bg {
1510 background-color: @alert3;
1509 background-color: @alert3;
1511 }
1510 }
1512
1511
1513 .color-r-bg {
1512 .color-r-bg {
1514 background-color: @alert2;
1513 background-color: @alert2;
1515 }
1514 }
1516
1515
1517 .color-a-border {
1516 .color-a-border {
1518 border: 1px solid @alert1;
1517 border: 1px solid @alert1;
1519 }
1518 }
1520
1519
1521 .color-c-border {
1520 .color-c-border {
1522 border: 1px solid @alert3;
1521 border: 1px solid @alert3;
1523 }
1522 }
1524
1523
1525 .color-r-border {
1524 .color-r-border {
1526 border: 1px solid @alert2;
1525 border: 1px solid @alert2;
1527 }
1526 }
1528
1527
1529 .commit-change-indicator {
1528 .commit-change-indicator {
1530 width: 15px;
1529 width: 15px;
1531 height: 15px;
1530 height: 15px;
1532 position: relative;
1531 position: relative;
1533 left: 15px;
1532 left: 15px;
1534 }
1533 }
1535
1534
1536 .commit-change-content {
1535 .commit-change-content {
1537 text-align: center;
1536 text-align: center;
1538 vertical-align: middle;
1537 vertical-align: middle;
1539 line-height: 15px;
1538 line-height: 15px;
1540 }
1539 }
1541 }
1540 }
1542
1541
1543 .compare_view_filepath {
1542 .compare_view_filepath {
1544 color: @grey1;
1543 color: @grey1;
1545 }
1544 }
1546
1545
1547 .show_more {
1546 .show_more {
1548 display: inline-block;
1547 display: inline-block;
1549 position: relative;
1548 width: 0;
1549 height: 0;
1550 vertical-align: middle;
1550 vertical-align: middle;
1551 width: 4px;
1551 content: "";
1552 height: @basefontsize;
1552 border: 4px solid;
1553
1553 border-right-color: transparent;
1554 &:after {
1554 border-bottom-color: transparent;
1555 content: "\00A0\25BE";
1555 border-left-color: transparent;
1556 display: inline-block;
1556 font-size: 0;
1557 width:10px;
1558 line-height: 5px;
1559 font-size: 12px;
1560 cursor: pointer;
1561 }
1562 }
1557 }
1563
1558
1564 .journal_more .show_more {
1559 .journal_more .show_more {
1565 display: inline;
1560 display: inline;
1566
1561
1567 &:after {
1562 &:after {
1568 content: none;
1563 content: none;
1569 }
1564 }
1570 }
1565 }
1571
1566
1572 .open .show_more:after,
1573 .select2-dropdown-open .show_more:after {
1574 .rotate(180deg);
1575 margin-left: 4px;
1576 }
1577
1578
1579 .compare_view_commits .collapse_commit:after {
1567 .compare_view_commits .collapse_commit:after {
1580 cursor: pointer;
1568 cursor: pointer;
1581 content: "\00A0\25B4";
1569 content: "\00A0\25B4";
1582 margin-left: -3px;
1570 margin-left: -3px;
1583 font-size: 17px;
1571 font-size: 17px;
1584 color: @grey4;
1572 color: @grey4;
1585 }
1573 }
1586
1574
1587 .diff_links {
1575 .diff_links {
1588 margin-left: 8px;
1576 margin-left: 8px;
1589 }
1577 }
1590
1578
1591 div.ancestor {
1579 div.ancestor {
1592 margin: -30px 0px;
1580 margin: -30px 0px;
1593 }
1581 }
1594
1582
1595 .cs_icon_td input[type="checkbox"] {
1583 .cs_icon_td input[type="checkbox"] {
1596 display: none;
1584 display: none;
1597 }
1585 }
1598
1586
1599 .cs_icon_td .expand_file_icon:after {
1587 .cs_icon_td .expand_file_icon:after {
1600 cursor: pointer;
1588 cursor: pointer;
1601 content: "\00A0\25B6";
1589 content: "\00A0\25B6";
1602 font-size: 12px;
1590 font-size: 12px;
1603 color: @grey4;
1591 color: @grey4;
1604 }
1592 }
1605
1593
1606 .cs_icon_td .collapse_file_icon:after {
1594 .cs_icon_td .collapse_file_icon:after {
1607 cursor: pointer;
1595 cursor: pointer;
1608 content: "\00A0\25BC";
1596 content: "\00A0\25BC";
1609 font-size: 12px;
1597 font-size: 12px;
1610 color: @grey4;
1598 color: @grey4;
1611 }
1599 }
1612
1600
1613 /*new binary
1601 /*new binary
1614 NEW_FILENODE = 1
1602 NEW_FILENODE = 1
1615 DEL_FILENODE = 2
1603 DEL_FILENODE = 2
1616 MOD_FILENODE = 3
1604 MOD_FILENODE = 3
1617 RENAMED_FILENODE = 4
1605 RENAMED_FILENODE = 4
1618 COPIED_FILENODE = 5
1606 COPIED_FILENODE = 5
1619 CHMOD_FILENODE = 6
1607 CHMOD_FILENODE = 6
1620 BIN_FILENODE = 7
1608 BIN_FILENODE = 7
1621 */
1609 */
1622 .cs_files_expand {
1610 .cs_files_expand {
1623 font-size: @basefontsize + 5px;
1611 font-size: @basefontsize + 5px;
1624 line-height: 1.8em;
1612 line-height: 1.8em;
1625 float: right;
1613 float: right;
1626 }
1614 }
1627
1615
1628 .cs_files_expand span{
1616 .cs_files_expand span{
1629 color: @rcblue;
1617 color: @rcblue;
1630 cursor: pointer;
1618 cursor: pointer;
1631 }
1619 }
1632 .cs_files {
1620 .cs_files {
1633 clear: both;
1621 clear: both;
1634 padding-bottom: @padding;
1622 padding-bottom: @padding;
1635
1623
1636 .cur_cs {
1624 .cur_cs {
1637 margin: 10px 2px;
1625 margin: 10px 2px;
1638 font-weight: bold;
1626 font-weight: bold;
1639 }
1627 }
1640
1628
1641 .node {
1629 .node {
1642 float: left;
1630 float: left;
1643 }
1631 }
1644
1632
1645 .changes {
1633 .changes {
1646 float: right;
1634 float: right;
1647 color: white;
1635 color: white;
1648 font-size: @basefontsize - 4px;
1636 font-size: @basefontsize - 4px;
1649 margin-top: 4px;
1637 margin-top: 4px;
1650 opacity: 0.6;
1638 opacity: 0.6;
1651 filter: Alpha(opacity=60); /* IE8 and earlier */
1639 filter: Alpha(opacity=60); /* IE8 and earlier */
1652
1640
1653 .added {
1641 .added {
1654 background-color: @alert1;
1642 background-color: @alert1;
1655 float: left;
1643 float: left;
1656 text-align: center;
1644 text-align: center;
1657 }
1645 }
1658
1646
1659 .deleted {
1647 .deleted {
1660 background-color: @alert2;
1648 background-color: @alert2;
1661 float: left;
1649 float: left;
1662 text-align: center;
1650 text-align: center;
1663 }
1651 }
1664
1652
1665 .bin {
1653 .bin {
1666 background-color: @alert1;
1654 background-color: @alert1;
1667 text-align: center;
1655 text-align: center;
1668 }
1656 }
1669
1657
1670 /*new binary*/
1658 /*new binary*/
1671 .bin.bin1 {
1659 .bin.bin1 {
1672 background-color: @alert1;
1660 background-color: @alert1;
1673 text-align: center;
1661 text-align: center;
1674 }
1662 }
1675
1663
1676 /*deleted binary*/
1664 /*deleted binary*/
1677 .bin.bin2 {
1665 .bin.bin2 {
1678 background-color: @alert2;
1666 background-color: @alert2;
1679 text-align: center;
1667 text-align: center;
1680 }
1668 }
1681
1669
1682 /*mod binary*/
1670 /*mod binary*/
1683 .bin.bin3 {
1671 .bin.bin3 {
1684 background-color: @grey2;
1672 background-color: @grey2;
1685 text-align: center;
1673 text-align: center;
1686 }
1674 }
1687
1675
1688 /*rename file*/
1676 /*rename file*/
1689 .bin.bin4 {
1677 .bin.bin4 {
1690 background-color: @alert4;
1678 background-color: @alert4;
1691 text-align: center;
1679 text-align: center;
1692 }
1680 }
1693
1681
1694 /*copied file*/
1682 /*copied file*/
1695 .bin.bin5 {
1683 .bin.bin5 {
1696 background-color: @alert4;
1684 background-color: @alert4;
1697 text-align: center;
1685 text-align: center;
1698 }
1686 }
1699
1687
1700 /*chmod file*/
1688 /*chmod file*/
1701 .bin.bin6 {
1689 .bin.bin6 {
1702 background-color: @grey2;
1690 background-color: @grey2;
1703 text-align: center;
1691 text-align: center;
1704 }
1692 }
1705 }
1693 }
1706 }
1694 }
1707
1695
1708 .cs_files .cs_added, .cs_files .cs_A,
1696 .cs_files .cs_added, .cs_files .cs_A,
1709 .cs_files .cs_added, .cs_files .cs_M,
1697 .cs_files .cs_added, .cs_files .cs_M,
1710 .cs_files .cs_added, .cs_files .cs_D {
1698 .cs_files .cs_added, .cs_files .cs_D {
1711 height: 16px;
1699 height: 16px;
1712 padding-right: 10px;
1700 padding-right: 10px;
1713 margin-top: 7px;
1701 margin-top: 7px;
1714 text-align: left;
1702 text-align: left;
1715 }
1703 }
1716
1704
1717 .cs_icon_td {
1705 .cs_icon_td {
1718 min-width: 16px;
1706 min-width: 16px;
1719 width: 16px;
1707 width: 16px;
1720 }
1708 }
1721
1709
1722 .pull-request-merge {
1710 .pull-request-merge {
1723 border: 1px solid @grey5;
1711 border: 1px solid @grey5;
1724 padding: 10px 0px 20px;
1712 padding: 10px 0px 20px;
1725 margin-top: 10px;
1713 margin-top: 10px;
1726 margin-bottom: 20px;
1714 margin-bottom: 20px;
1727 }
1715 }
1728
1716
1729 .pull-request-merge ul {
1717 .pull-request-merge ul {
1730 padding: 0px 0px;
1718 padding: 0px 0px;
1731 }
1719 }
1732
1720
1733 .pull-request-merge li:before{
1721 .pull-request-merge li:before{
1734 content:none;
1722 content:none;
1735 }
1723 }
1736
1724
1737 .pull-request-merge .pull-request-wrap {
1725 .pull-request-merge .pull-request-wrap {
1738 height: auto;
1726 height: auto;
1739 padding: 0px 0px;
1727 padding: 0px 0px;
1740 text-align: right;
1728 text-align: right;
1741 }
1729 }
1742
1730
1743 .pull-request-merge span {
1731 .pull-request-merge span {
1744 margin-right: 5px;
1732 margin-right: 5px;
1745 }
1733 }
1746
1734
1747 .pull-request-merge-actions {
1735 .pull-request-merge-actions {
1748 min-height: 30px;
1736 min-height: 30px;
1749 padding: 0px 0px;
1737 padding: 0px 0px;
1750 }
1738 }
1751
1739
1752 .pull-request-merge-info {
1740 .pull-request-merge-info {
1753 padding: 0px 5px 5px 0px;
1741 padding: 0px 5px 5px 0px;
1754 }
1742 }
1755
1743
1756 .merge-status {
1744 .merge-status {
1757 margin-right: 5px;
1745 margin-right: 5px;
1758 }
1746 }
1759
1747
1760 .merge-message {
1748 .merge-message {
1761 font-size: 1.2em
1749 font-size: 1.2em
1762 }
1750 }
1763
1751
1764 .merge-message.success i,
1752 .merge-message.success i,
1765 .merge-icon.success i {
1753 .merge-icon.success i {
1766 color:@alert1;
1754 color:@alert1;
1767 }
1755 }
1768
1756
1769 .merge-message.warning i,
1757 .merge-message.warning i,
1770 .merge-icon.warning i {
1758 .merge-icon.warning i {
1771 color: @alert3;
1759 color: @alert3;
1772 }
1760 }
1773
1761
1774 .merge-message.error i,
1762 .merge-message.error i,
1775 .merge-icon.error i {
1763 .merge-icon.error i {
1776 color:@alert2;
1764 color:@alert2;
1777 }
1765 }
1778
1766
1779 .pr-versions {
1767 .pr-versions {
1780 font-size: 1.1em;
1768 font-size: 1.1em;
1781
1769
1782 table {
1770 table {
1783 padding: 0px 5px;
1771 padding: 0px 5px;
1784 }
1772 }
1785
1773
1786 td {
1774 td {
1787 line-height: 15px;
1775 line-height: 15px;
1788 }
1776 }
1789
1777
1790 .flag_status {
1778 .flag_status {
1791 margin: 0;
1779 margin: 0;
1792 }
1780 }
1793
1781
1794 .compare-radio-button {
1782 .compare-radio-button {
1795 position: relative;
1783 position: relative;
1796 top: -3px;
1784 top: -3px;
1797 }
1785 }
1798 }
1786 }
1799
1787
1800
1788
1801 #close_pull_request {
1789 #close_pull_request {
1802 margin-right: 0px;
1790 margin-right: 0px;
1803 }
1791 }
1804
1792
1805 .empty_data {
1793 .empty_data {
1806 color: @grey4;
1794 color: @grey4;
1807 }
1795 }
1808
1796
1809 #changeset_compare_view_content {
1797 #changeset_compare_view_content {
1810 margin-bottom: @space;
1798 margin-bottom: @space;
1811 clear: both;
1799 clear: both;
1812 width: 100%;
1800 width: 100%;
1813 box-sizing: border-box;
1801 box-sizing: border-box;
1814 .border-radius(@border-radius);
1802 .border-radius(@border-radius);
1815
1803
1816 .help-block {
1804 .help-block {
1817 margin: @padding 0;
1805 margin: @padding 0;
1818 color: @text-color;
1806 color: @text-color;
1819 &.pre-formatting {
1807 &.pre-formatting {
1820 white-space: pre;
1808 white-space: pre;
1821 }
1809 }
1822 }
1810 }
1823
1811
1824 .empty_data {
1812 .empty_data {
1825 margin: @padding 0;
1813 margin: @padding 0;
1826 }
1814 }
1827
1815
1828 .alert {
1816 .alert {
1829 margin-bottom: @space;
1817 margin-bottom: @space;
1830 }
1818 }
1831 }
1819 }
1832
1820
1833 .table_disp {
1821 .table_disp {
1834 .status {
1822 .status {
1835 width: auto;
1823 width: auto;
1836
1824
1837 .flag_status {
1825 .flag_status {
1838 float: left;
1826 float: left;
1839 }
1827 }
1840 }
1828 }
1841 }
1829 }
1842
1830
1843
1831
1844 .creation_in_progress {
1832 .creation_in_progress {
1845 color: @grey4
1833 color: @grey4
1846 }
1834 }
1847
1835
1848 .status_box_menu {
1836 .status_box_menu {
1849 margin: 0;
1837 margin: 0;
1850 }
1838 }
1851
1839
1852 .notification-table{
1840 .notification-table{
1853 margin-bottom: @space;
1841 margin-bottom: @space;
1854 display: table;
1842 display: table;
1855 width: 100%;
1843 width: 100%;
1856
1844
1857 .container{
1845 .container{
1858 display: table-row;
1846 display: table-row;
1859
1847
1860 .notification-header{
1848 .notification-header{
1861 border-bottom: @border-thickness solid @border-default-color;
1849 border-bottom: @border-thickness solid @border-default-color;
1862 }
1850 }
1863
1851
1864 .notification-subject{
1852 .notification-subject{
1865 display: table-cell;
1853 display: table-cell;
1866 }
1854 }
1867 }
1855 }
1868 }
1856 }
1869
1857
1870 // Notifications
1858 // Notifications
1871 .notification-header{
1859 .notification-header{
1872 display: table;
1860 display: table;
1873 width: 100%;
1861 width: 100%;
1874 padding: floor(@basefontsize/2) 0;
1862 padding: floor(@basefontsize/2) 0;
1875 line-height: 1em;
1863 line-height: 1em;
1876
1864
1877 .desc, .delete-notifications, .read-notifications{
1865 .desc, .delete-notifications, .read-notifications{
1878 display: table-cell;
1866 display: table-cell;
1879 text-align: left;
1867 text-align: left;
1880 }
1868 }
1881
1869
1882 .desc{
1870 .desc{
1883 width: 1163px;
1871 width: 1163px;
1884 }
1872 }
1885
1873
1886 .delete-notifications, .read-notifications{
1874 .delete-notifications, .read-notifications{
1887 width: 35px;
1875 width: 35px;
1888 min-width: 35px; //fixes when only one button is displayed
1876 min-width: 35px; //fixes when only one button is displayed
1889 }
1877 }
1890 }
1878 }
1891
1879
1892 .notification-body {
1880 .notification-body {
1893 .markdown-block,
1881 .markdown-block,
1894 .rst-block {
1882 .rst-block {
1895 padding: @padding 0;
1883 padding: @padding 0;
1896 }
1884 }
1897
1885
1898 .notification-subject {
1886 .notification-subject {
1899 padding: @textmargin 0;
1887 padding: @textmargin 0;
1900 border-bottom: @border-thickness solid @border-default-color;
1888 border-bottom: @border-thickness solid @border-default-color;
1901 }
1889 }
1902 }
1890 }
1903
1891
1904
1892
1905 .notifications_buttons{
1893 .notifications_buttons{
1906 float: right;
1894 float: right;
1907 }
1895 }
1908
1896
1909 #notification-status{
1897 #notification-status{
1910 display: inline;
1898 display: inline;
1911 }
1899 }
1912
1900
1913 // Repositories
1901 // Repositories
1914
1902
1915 #summary.fields{
1903 #summary.fields{
1916 display: table;
1904 display: table;
1917
1905
1918 .field{
1906 .field{
1919 display: table-row;
1907 display: table-row;
1920
1908
1921 .label-summary{
1909 .label-summary{
1922 display: table-cell;
1910 display: table-cell;
1923 min-width: @label-summary-minwidth;
1911 min-width: @label-summary-minwidth;
1924 padding-top: @padding/2;
1912 padding-top: @padding/2;
1925 padding-bottom: @padding/2;
1913 padding-bottom: @padding/2;
1926 padding-right: @padding/2;
1914 padding-right: @padding/2;
1927 }
1915 }
1928
1916
1929 .input{
1917 .input{
1930 display: table-cell;
1918 display: table-cell;
1931 padding: @padding/2;
1919 padding: @padding/2;
1932
1920
1933 input{
1921 input{
1934 min-width: 29em;
1922 min-width: 29em;
1935 padding: @padding/4;
1923 padding: @padding/4;
1936 }
1924 }
1937 }
1925 }
1938 .statistics, .downloads{
1926 .statistics, .downloads{
1939 .disabled{
1927 .disabled{
1940 color: @grey4;
1928 color: @grey4;
1941 }
1929 }
1942 }
1930 }
1943 }
1931 }
1944 }
1932 }
1945
1933
1946 #summary{
1934 #summary{
1947 width: 70%;
1935 width: 70%;
1948 }
1936 }
1949
1937
1950
1938
1951 // Journal
1939 // Journal
1952 .journal.title {
1940 .journal.title {
1953 h5 {
1941 h5 {
1954 float: left;
1942 float: left;
1955 margin: 0;
1943 margin: 0;
1956 width: 70%;
1944 width: 70%;
1957 }
1945 }
1958
1946
1959 ul {
1947 ul {
1960 float: right;
1948 float: right;
1961 display: inline-block;
1949 display: inline-block;
1962 margin: 0;
1950 margin: 0;
1963 width: 30%;
1951 width: 30%;
1964 text-align: right;
1952 text-align: right;
1965
1953
1966 li {
1954 li {
1967 display: inline;
1955 display: inline;
1968 font-size: @journal-fontsize;
1956 font-size: @journal-fontsize;
1969 line-height: 1em;
1957 line-height: 1em;
1970
1958
1971 &:before { content: none; }
1959 &:before { content: none; }
1972 }
1960 }
1973 }
1961 }
1974 }
1962 }
1975
1963
1976 .filterexample {
1964 .filterexample {
1977 position: absolute;
1965 position: absolute;
1978 top: 95px;
1966 top: 95px;
1979 left: @contentpadding;
1967 left: @contentpadding;
1980 color: @rcblue;
1968 color: @rcblue;
1981 font-size: 11px;
1969 font-size: 11px;
1982 font-family: @text-regular;
1970 font-family: @text-regular;
1983 cursor: help;
1971 cursor: help;
1984
1972
1985 &:hover {
1973 &:hover {
1986 color: @rcdarkblue;
1974 color: @rcdarkblue;
1987 }
1975 }
1988
1976
1989 @media (max-width:768px) {
1977 @media (max-width:768px) {
1990 position: relative;
1978 position: relative;
1991 top: auto;
1979 top: auto;
1992 left: auto;
1980 left: auto;
1993 display: block;
1981 display: block;
1994 }
1982 }
1995 }
1983 }
1996
1984
1997
1985
1998 #journal{
1986 #journal{
1999 margin-bottom: @space;
1987 margin-bottom: @space;
2000
1988
2001 .journal_day{
1989 .journal_day{
2002 margin-bottom: @textmargin/2;
1990 margin-bottom: @textmargin/2;
2003 padding-bottom: @textmargin/2;
1991 padding-bottom: @textmargin/2;
2004 font-size: @journal-fontsize;
1992 font-size: @journal-fontsize;
2005 border-bottom: @border-thickness solid @border-default-color;
1993 border-bottom: @border-thickness solid @border-default-color;
2006 }
1994 }
2007
1995
2008 .journal_container{
1996 .journal_container{
2009 margin-bottom: @space;
1997 margin-bottom: @space;
2010
1998
2011 .journal_user{
1999 .journal_user{
2012 display: inline-block;
2000 display: inline-block;
2013 }
2001 }
2014 .journal_action_container{
2002 .journal_action_container{
2015 display: block;
2003 display: block;
2016 margin-top: @textmargin;
2004 margin-top: @textmargin;
2017
2005
2018 div{
2006 div{
2019 display: inline;
2007 display: inline;
2020 }
2008 }
2021
2009
2022 div.journal_action_params{
2010 div.journal_action_params{
2023 display: block;
2011 display: block;
2024 }
2012 }
2025
2013
2026 div.journal_repo:after{
2014 div.journal_repo:after{
2027 content: "\A";
2015 content: "\A";
2028 white-space: pre;
2016 white-space: pre;
2029 }
2017 }
2030
2018
2031 div.date{
2019 div.date{
2032 display: block;
2020 display: block;
2033 margin-bottom: @textmargin;
2021 margin-bottom: @textmargin;
2034 }
2022 }
2035 }
2023 }
2036 }
2024 }
2037 }
2025 }
2038
2026
2039 // Files
2027 // Files
2040 .edit-file-title {
2028 .edit-file-title {
2041 border-bottom: @border-thickness solid @border-default-color;
2029 border-bottom: @border-thickness solid @border-default-color;
2042
2030
2043 .breadcrumbs {
2031 .breadcrumbs {
2044 margin-bottom: 0;
2032 margin-bottom: 0;
2045 }
2033 }
2046 }
2034 }
2047
2035
2048 .edit-file-fieldset {
2036 .edit-file-fieldset {
2049 margin-top: @sidebarpadding;
2037 margin-top: @sidebarpadding;
2050
2038
2051 .fieldset {
2039 .fieldset {
2052 .left-label {
2040 .left-label {
2053 width: 13%;
2041 width: 13%;
2054 }
2042 }
2055 .right-content {
2043 .right-content {
2056 width: 87%;
2044 width: 87%;
2057 max-width: 100%;
2045 max-width: 100%;
2058 }
2046 }
2059 .filename-label {
2047 .filename-label {
2060 margin-top: 13px;
2048 margin-top: 13px;
2061 }
2049 }
2062 .commit-message-label {
2050 .commit-message-label {
2063 margin-top: 4px;
2051 margin-top: 4px;
2064 }
2052 }
2065 .file-upload-input {
2053 .file-upload-input {
2066 input {
2054 input {
2067 display: none;
2055 display: none;
2068 }
2056 }
2069 margin-top: 10px;
2057 margin-top: 10px;
2070 }
2058 }
2071 .file-upload-label {
2059 .file-upload-label {
2072 margin-top: 10px;
2060 margin-top: 10px;
2073 }
2061 }
2074 p {
2062 p {
2075 margin-top: 5px;
2063 margin-top: 5px;
2076 }
2064 }
2077
2065
2078 }
2066 }
2079 .custom-path-link {
2067 .custom-path-link {
2080 margin-left: 5px;
2068 margin-left: 5px;
2081 }
2069 }
2082 #commit {
2070 #commit {
2083 resize: vertical;
2071 resize: vertical;
2084 }
2072 }
2085 }
2073 }
2086
2074
2087 .delete-file-preview {
2075 .delete-file-preview {
2088 max-height: 250px;
2076 max-height: 250px;
2089 }
2077 }
2090
2078
2091 .new-file,
2079 .new-file,
2092 #filter_activate,
2080 #filter_activate,
2093 #filter_deactivate {
2081 #filter_deactivate {
2094 float: left;
2082 float: left;
2095 margin: 0 0 0 15px;
2083 margin: 0 0 0 15px;
2096 }
2084 }
2097
2085
2098 h3.files_location{
2086 h3.files_location{
2099 line-height: 2.4em;
2087 line-height: 2.4em;
2100 }
2088 }
2101
2089
2102 .browser-nav {
2090 .browser-nav {
2103 display: table;
2091 display: table;
2104 margin-bottom: @space;
2092 margin-bottom: @space;
2105
2093
2106
2094
2107 .info_box {
2095 .info_box {
2108 display: inline-table;
2096 display: inline-table;
2109 height: 2.5em;
2097 height: 2.5em;
2110
2098
2111 .browser-cur-rev, .info_box_elem {
2099 .browser-cur-rev, .info_box_elem {
2112 display: table-cell;
2100 display: table-cell;
2113 vertical-align: middle;
2101 vertical-align: middle;
2114 }
2102 }
2115
2103
2116 .info_box_elem {
2104 .info_box_elem {
2117 border-top: @border-thickness solid @rcblue;
2105 border-top: @border-thickness solid @rcblue;
2118 border-bottom: @border-thickness solid @rcblue;
2106 border-bottom: @border-thickness solid @rcblue;
2119
2107
2120 #at_rev, a {
2108 #at_rev, a {
2121 padding: 0.6em 0.9em;
2109 padding: 0.6em 0.9em;
2122 margin: 0;
2110 margin: 0;
2123 .box-shadow(none);
2111 .box-shadow(none);
2124 border: 0;
2112 border: 0;
2125 height: 12px;
2113 height: 12px;
2126 }
2114 }
2127
2115
2128 input#at_rev {
2116 input#at_rev {
2129 max-width: 50px;
2117 max-width: 50px;
2130 text-align: right;
2118 text-align: right;
2131 }
2119 }
2132
2120
2133 &.previous {
2121 &.previous {
2134 border: @border-thickness solid @rcblue;
2122 border: @border-thickness solid @rcblue;
2135 .disabled {
2123 .disabled {
2136 color: @grey4;
2124 color: @grey4;
2137 cursor: not-allowed;
2125 cursor: not-allowed;
2138 }
2126 }
2139 }
2127 }
2140
2128
2141 &.next {
2129 &.next {
2142 border: @border-thickness solid @rcblue;
2130 border: @border-thickness solid @rcblue;
2143 .disabled {
2131 .disabled {
2144 color: @grey4;
2132 color: @grey4;
2145 cursor: not-allowed;
2133 cursor: not-allowed;
2146 }
2134 }
2147 }
2135 }
2148 }
2136 }
2149
2137
2150 .browser-cur-rev {
2138 .browser-cur-rev {
2151
2139
2152 span{
2140 span{
2153 margin: 0;
2141 margin: 0;
2154 color: @rcblue;
2142 color: @rcblue;
2155 height: 12px;
2143 height: 12px;
2156 display: inline-block;
2144 display: inline-block;
2157 padding: 0.7em 1em ;
2145 padding: 0.7em 1em ;
2158 border: @border-thickness solid @rcblue;
2146 border: @border-thickness solid @rcblue;
2159 margin-right: @padding;
2147 margin-right: @padding;
2160 }
2148 }
2161 }
2149 }
2162 }
2150 }
2163
2151
2164 .search_activate {
2152 .search_activate {
2165 display: table-cell;
2153 display: table-cell;
2166 vertical-align: middle;
2154 vertical-align: middle;
2167
2155
2168 input, label{
2156 input, label{
2169 margin: 0;
2157 margin: 0;
2170 padding: 0;
2158 padding: 0;
2171 }
2159 }
2172
2160
2173 input{
2161 input{
2174 margin-left: @textmargin;
2162 margin-left: @textmargin;
2175 }
2163 }
2176
2164
2177 }
2165 }
2178 }
2166 }
2179
2167
2180 .browser-cur-rev{
2168 .browser-cur-rev{
2181 margin-bottom: @textmargin;
2169 margin-bottom: @textmargin;
2182 }
2170 }
2183
2171
2184 #node_filter_box_loading{
2172 #node_filter_box_loading{
2185 .info_text;
2173 .info_text;
2186 }
2174 }
2187
2175
2188 .browser-search {
2176 .browser-search {
2189 margin: -25px 0px 5px 0px;
2177 margin: -25px 0px 5px 0px;
2190 }
2178 }
2191
2179
2192 .node-filter {
2180 .node-filter {
2193 font-size: @repo-title-fontsize;
2181 font-size: @repo-title-fontsize;
2194 padding: 4px 0px 0px 0px;
2182 padding: 4px 0px 0px 0px;
2195
2183
2196 .node-filter-path {
2184 .node-filter-path {
2197 float: left;
2185 float: left;
2198 color: @grey4;
2186 color: @grey4;
2199 }
2187 }
2200 .node-filter-input {
2188 .node-filter-input {
2201 float: left;
2189 float: left;
2202 margin: -2px 0px 0px 2px;
2190 margin: -2px 0px 0px 2px;
2203 input {
2191 input {
2204 padding: 2px;
2192 padding: 2px;
2205 border: none;
2193 border: none;
2206 font-size: @repo-title-fontsize;
2194 font-size: @repo-title-fontsize;
2207 }
2195 }
2208 }
2196 }
2209 }
2197 }
2210
2198
2211
2199
2212 .browser-result{
2200 .browser-result{
2213 td a{
2201 td a{
2214 margin-left: 0.5em;
2202 margin-left: 0.5em;
2215 display: inline-block;
2203 display: inline-block;
2216
2204
2217 em{
2205 em{
2218 font-family: @text-bold;
2206 font-family: @text-bold;
2219 }
2207 }
2220 }
2208 }
2221 }
2209 }
2222
2210
2223 .browser-highlight{
2211 .browser-highlight{
2224 background-color: @grey5-alpha;
2212 background-color: @grey5-alpha;
2225 }
2213 }
2226
2214
2227
2215
2228 // Search
2216 // Search
2229
2217
2230 .search-form{
2218 .search-form{
2231 #q {
2219 #q {
2232 width: @search-form-width;
2220 width: @search-form-width;
2233 }
2221 }
2234 .fields{
2222 .fields{
2235 margin: 0 0 @space;
2223 margin: 0 0 @space;
2236 }
2224 }
2237
2225
2238 label{
2226 label{
2239 display: inline-block;
2227 display: inline-block;
2240 margin-right: @textmargin;
2228 margin-right: @textmargin;
2241 padding-top: 0.25em;
2229 padding-top: 0.25em;
2242 }
2230 }
2243
2231
2244
2232
2245 .results{
2233 .results{
2246 clear: both;
2234 clear: both;
2247 margin: 0 0 @padding;
2235 margin: 0 0 @padding;
2248 }
2236 }
2249 }
2237 }
2250
2238
2251 div.search-feedback-items {
2239 div.search-feedback-items {
2252 display: inline-block;
2240 display: inline-block;
2253 padding:0px 0px 0px 96px;
2254 }
2241 }
2255
2242
2256 div.search-code-body {
2243 div.search-code-body {
2257 background-color: #ffffff; padding: 5px 0 5px 10px;
2244 background-color: #ffffff; padding: 5px 0 5px 10px;
2258 pre {
2245 pre {
2259 .match { background-color: #faffa6;}
2246 .match { background-color: #faffa6;}
2260 .break { display: block; width: 100%; background-color: #DDE7EF; color: #747474; }
2247 .break { display: block; width: 100%; background-color: #DDE7EF; color: #747474; }
2261 }
2248 }
2262 }
2249 }
2263
2250
2264 .expand_commit.search {
2251 .expand_commit.search {
2265 .show_more.open {
2252 .show_more.open {
2266 height: auto;
2253 height: auto;
2267 max-height: none;
2254 max-height: none;
2268 }
2255 }
2269 }
2256 }
2270
2257
2271 .search-results {
2258 .search-results {
2272
2259
2273 h2 {
2260 h2 {
2274 margin-bottom: 0;
2261 margin-bottom: 0;
2275 }
2262 }
2276 .codeblock {
2263 .codeblock {
2277 border: none;
2264 border: none;
2278 background: transparent;
2265 background: transparent;
2279 }
2266 }
2280
2267
2281 .codeblock-header {
2268 .codeblock-header {
2282 border: none;
2269 border: none;
2283 background: transparent;
2270 background: transparent;
2284 }
2271 }
2285
2272
2286 .code-body {
2273 .code-body {
2287 border: @border-thickness solid @border-default-color;
2274 border: @border-thickness solid @border-default-color;
2288 .border-radius(@border-radius);
2275 .border-radius(@border-radius);
2289 }
2276 }
2290
2277
2291 .td-commit {
2278 .td-commit {
2292 &:extend(pre);
2279 &:extend(pre);
2293 border-bottom: @border-thickness solid @border-default-color;
2280 border-bottom: @border-thickness solid @border-default-color;
2294 }
2281 }
2295
2282
2296 .message {
2283 .message {
2297 height: auto;
2284 height: auto;
2298 max-width: 350px;
2285 max-width: 350px;
2299 white-space: normal;
2286 white-space: normal;
2300 text-overflow: initial;
2287 text-overflow: initial;
2301 overflow: visible;
2288 overflow: visible;
2302
2289
2303 .match { background-color: #faffa6;}
2290 .match { background-color: #faffa6;}
2304 .break { background-color: #DDE7EF; width: 100%; color: #747474; display: block; }
2291 .break { background-color: #DDE7EF; width: 100%; color: #747474; display: block; }
2305 }
2292 }
2306
2293
2307 }
2294 }
2308
2295
2309 table.rctable td.td-search-results div {
2296 table.rctable td.td-search-results div {
2310 max-width: 100%;
2297 max-width: 100%;
2311 }
2298 }
2312
2299
2313 #tip-box, .tip-box{
2300 #tip-box, .tip-box{
2314 padding: @menupadding/2;
2301 padding: @menupadding/2;
2315 display: block;
2302 display: block;
2316 border: @border-thickness solid @border-highlight-color;
2303 border: @border-thickness solid @border-highlight-color;
2317 .border-radius(@border-radius);
2304 .border-radius(@border-radius);
2318 background-color: white;
2305 background-color: white;
2319 z-index: 99;
2306 z-index: 99;
2320 white-space: pre-wrap;
2307 white-space: pre-wrap;
2321 }
2308 }
2322
2309
2323 #linktt {
2310 #linktt {
2324 width: 79px;
2311 width: 79px;
2325 }
2312 }
2326
2313
2327 #help_kb .modal-content{
2314 #help_kb .modal-content{
2328 max-width: 750px;
2315 max-width: 750px;
2329 margin: 10% auto;
2316 margin: 10% auto;
2330
2317
2331 table{
2318 table{
2332 td,th{
2319 td,th{
2333 border-bottom: none;
2320 border-bottom: none;
2334 line-height: 2.5em;
2321 line-height: 2.5em;
2335 }
2322 }
2336 th{
2323 th{
2337 padding-bottom: @textmargin/2;
2324 padding-bottom: @textmargin/2;
2338 }
2325 }
2339 td.keys{
2326 td.keys{
2340 text-align: center;
2327 text-align: center;
2341 }
2328 }
2342 }
2329 }
2343
2330
2344 .block-left{
2331 .block-left{
2345 width: 45%;
2332 width: 45%;
2346 margin-right: 5%;
2333 margin-right: 5%;
2347 }
2334 }
2348 .modal-footer{
2335 .modal-footer{
2349 clear: both;
2336 clear: both;
2350 }
2337 }
2351 .key.tag{
2338 .key.tag{
2352 padding: 0.5em;
2339 padding: 0.5em;
2353 background-color: @rcblue;
2340 background-color: @rcblue;
2354 color: white;
2341 color: white;
2355 border-color: @rcblue;
2342 border-color: @rcblue;
2356 .box-shadow(none);
2343 .box-shadow(none);
2357 }
2344 }
2358 }
2345 }
2359
2346
2360
2347
2361
2348
2362 //--- IMPORTS FOR REFACTORED STYLES ------------------//
2349 //--- IMPORTS FOR REFACTORED STYLES ------------------//
2363
2350
2364 @import 'statistics-graph';
2351 @import 'statistics-graph';
2365 @import 'tables';
2352 @import 'tables';
2366 @import 'forms';
2353 @import 'forms';
2367 @import 'diff';
2354 @import 'diff';
2368 @import 'summary';
2355 @import 'summary';
2369 @import 'navigation';
2356 @import 'navigation';
2370
2357
2371 //--- SHOW/HIDE SECTIONS --//
2358 //--- SHOW/HIDE SECTIONS --//
2372
2359
2373 .btn-collapse {
2360 .btn-collapse {
2374 float: right;
2361 float: right;
2375 text-align: right;
2362 text-align: right;
2376 font-family: @text-light;
2363 font-family: @text-light;
2377 font-size: @basefontsize;
2364 font-size: @basefontsize;
2378 cursor: pointer;
2365 cursor: pointer;
2379 border: none;
2366 border: none;
2380 color: @rcblue;
2367 color: @rcblue;
2381 }
2368 }
2382
2369
2383 table.rctable,
2370 table.rctable,
2384 table.dataTable {
2371 table.dataTable {
2385 .btn-collapse {
2372 .btn-collapse {
2386 float: right;
2373 float: right;
2387 text-align: right;
2374 text-align: right;
2388 }
2375 }
2389 }
2376 }
2390
2377
2391
2378
2392 // TODO: johbo: Fix for IE10, this avoids that we see a border
2379 // TODO: johbo: Fix for IE10, this avoids that we see a border
2393 // and padding around checkboxes and radio boxes. Move to the right place,
2380 // and padding around checkboxes and radio boxes. Move to the right place,
2394 // or better: Remove this once we did the form refactoring.
2381 // or better: Remove this once we did the form refactoring.
2395 input[type=checkbox],
2382 input[type=checkbox],
2396 input[type=radio] {
2383 input[type=radio] {
2397 padding: 0;
2384 padding: 0;
2398 border: none;
2385 border: none;
2399 }
2386 }
2400
2387
2401 .toggle-ajax-spinner{
2388 .toggle-ajax-spinner{
2402 height: 16px;
2389 height: 16px;
2403 width: 16px;
2390 width: 16px;
2404 }
2391 }
2405
2392
2406
2393
2407 .markup-form .clearfix {
2394 .markup-form .clearfix {
2408 .border-radius(@border-radius);
2395 .border-radius(@border-radius);
2409 margin: 0px;
2396 margin: 0px;
2410 }
2397 }
2411
2398
2412 .markup-form-area {
2399 .markup-form-area {
2413 padding: 8px 12px;
2400 padding: 8px 12px;
2414 border: 1px solid @grey4;
2401 border: 1px solid @grey4;
2415 .border-radius(@border-radius);
2402 .border-radius(@border-radius);
2416 }
2403 }
2417
2404
2418 .markup-form-area-header .nav-links {
2405 .markup-form-area-header .nav-links {
2419 display: flex;
2406 display: flex;
2420 flex-flow: row wrap;
2407 flex-flow: row wrap;
2421 -webkit-flex-flow: row wrap;
2408 -webkit-flex-flow: row wrap;
2422 width: 100%;
2409 width: 100%;
2423 }
2410 }
2424
2411
2425 .markup-form-area-footer {
2412 .markup-form-area-footer {
2426 display: flex;
2413 display: flex;
2427 }
2414 }
2428
2415
2429 .markup-form-area-footer .toolbar {
2416 .markup-form-area-footer .toolbar {
2430
2417
2431 }
2418 }
2432
2419
2433 // markup Form
2420 // markup Form
2434 div.markup-form {
2421 div.markup-form {
2435 margin-top: 20px;
2422 margin-top: 20px;
2436 }
2423 }
2437
2424
2438 .markup-form strong {
2425 .markup-form strong {
2439 display: block;
2426 display: block;
2440 margin-bottom: 15px;
2427 margin-bottom: 15px;
2441 }
2428 }
2442
2429
2443 .markup-form textarea {
2430 .markup-form textarea {
2444 width: 100%;
2431 width: 100%;
2445 height: 100px;
2432 height: 100px;
2446 font-family: 'Monaco', 'Courier', 'Courier New', monospace;
2433 font-family: 'Monaco', 'Courier', 'Courier New', monospace;
2447 }
2434 }
2448
2435
2449 form.markup-form {
2436 form.markup-form {
2450 margin-top: 10px;
2437 margin-top: 10px;
2451 margin-left: 10px;
2438 margin-left: 10px;
2452 }
2439 }
2453
2440
2454 .markup-form .comment-block-ta,
2441 .markup-form .comment-block-ta,
2455 .markup-form .preview-box {
2442 .markup-form .preview-box {
2456 .border-radius(@border-radius);
2443 .border-radius(@border-radius);
2457 .box-sizing(border-box);
2444 .box-sizing(border-box);
2458 background-color: white;
2445 background-color: white;
2459 }
2446 }
2460
2447
2461 .markup-form .preview-box.unloaded {
2448 .markup-form .preview-box.unloaded {
2462 height: 50px;
2449 height: 50px;
2463 text-align: center;
2450 text-align: center;
2464 padding: 20px;
2451 padding: 20px;
2465 background-color: white;
2452 background-color: white;
2466 }
2453 }
@@ -1,696 +1,692 b''
1 // navigation.less
1 // navigation.less
2 // For use in RhodeCode applications;
2 // For use in RhodeCode applications;
3 // see style guide documentation for guidelines.
3 // see style guide documentation for guidelines.
4
4
5 // HEADER NAVIGATION
5 // HEADER NAVIGATION
6
6
7 .horizontal-list {
7 .horizontal-list {
8 float: right;
8 float: right;
9 display: block;
9 display: block;
10 margin: 0;
10 margin: 0;
11 padding: 0;
11 padding: 0;
12 -webkit-padding-start: 0;
12 -webkit-padding-start: 0;
13 text-align: left;
13 text-align: left;
14 font-size: @navigation-fontsize;
14 font-size: @navigation-fontsize;
15 color: @grey6;
15 color: @grey6;
16 z-index:10;
16 z-index:10;
17
17
18 li {
18 li {
19 line-height: 1em;
19 line-height: 1em;
20 list-style-type: none;
20 list-style-type: none;
21
21
22 a {
22 a {
23 padding: 0 .5em;
23 padding: 0 .5em;
24
24
25 &.menu_link_notifications {
25 &.menu_link_notifications {
26 .pill(7px,@rcblue);
26 .pill(7px,@rcblue);
27 display: inline;
27 display: inline;
28 margin: 0 7px 0 .7em;
28 margin: 0 7px 0 .7em;
29 font-size: @basefontsize;
29 font-size: @basefontsize;
30 color: white;
30 color: white;
31
31
32 &.empty {
32 &.empty {
33 background-color: @grey4;
33 background-color: @grey4;
34 }
34 }
35
35
36 &:hover {
36 &:hover {
37 background-color: @rcdarkblue;
37 background-color: @rcdarkblue;
38 }
38 }
39 }
39 }
40 }
40 }
41 .pill_container {
41 .pill_container {
42 margin: 1.25em 0px 0px 0px;
42 margin: 1.25em 0px 0px 0px;
43 float: right;
43 float: right;
44 }
44 }
45
45
46 &#quick_login_li {
46 &#quick_login_li {
47 &:hover {
47 &:hover {
48 color: @grey5;
48 color: @grey5;
49 }
49 }
50
50
51 a.menu_link_notifications {
51 a.menu_link_notifications {
52 color: white;
52 color: white;
53 }
53 }
54
54
55 .user {
55 .user {
56 padding-bottom: 10px;
56 padding-bottom: 10px;
57 }
57 }
58
58
59 &.open {
59 &.open {
60 .user {
60 .user {
61 border-bottom: 5px solid @rcblue;
61 border-bottom: 5px solid @rcblue;
62 }
62 }
63 }
63 }
64 }
64 }
65
65
66 &:before { content: none; }
66 &:before { content: none; }
67
67
68 &:last-child {
68 &:last-child {
69 .menulabel {
69 .menulabel {
70 padding-right: 0;
70 padding-right: 0;
71 border-right: none;
71 border-right: none;
72
72
73 .show_more {
73 .show_more {
74 padding-right: 0;
74 padding-right: 0;
75 }
75 }
76 }
76 }
77
77
78 &> a {
78 &> a {
79 border-bottom: none;
79 border-bottom: none;
80 }
80 }
81 }
81 }
82
82
83 &.active {
83 &.active {
84 border-bottom: 5px solid @rcblue;
84 border-bottom: 5px solid @rcblue;
85 }
85 }
86
86
87 &.open {
87 &.open {
88
88
89 a {
89 a {
90 color: white;
90 color: white;
91 }
91 }
92 }
92 }
93
93
94 &:focus {
94 &:focus {
95 outline: none;
95 outline: none;
96 }
96 }
97
97
98 ul li {
98 ul li {
99 display: block;
99 display: block;
100
100
101 &:last-child> a {
101 &:last-child> a {
102 border-bottom: none;
102 border-bottom: none;
103 }
103 }
104
104
105 ul li:last-child a {
105 ul li:last-child a {
106 /* we don't expect more then 3 levels of submenu and the third
106 /* we don't expect more then 3 levels of submenu and the third
107 level can have different html structure */
107 level can have different html structure */
108 border-bottom: none;
108 border-bottom: none;
109 }
109 }
110 }
110 }
111 }
111 }
112
112
113 > li {
113 > li {
114 float: left;
114 float: left;
115 display: block;
115 display: block;
116 padding: 0;
116 padding: 0;
117
117
118 > a,
118 > a,
119 &.has_select2 a {
119 &.has_select2 a {
120 display: block;
120 display: block;
121 padding: 10px 0 2px;
121 padding: 10px 0 2px;
122
123 .show_more {
124 margin-top: -4px;
125 padding-right: .5em;
126 }
127 }
122 }
128
123
129 .menulabel {
124 .menulabel {
130 padding: 0 .5em;
125 padding: 0 .5em;
131 line-height: 1em;
126 line-height: 1em;
132 // for this specifically we do not use a variable
127 // for this specifically we do not use a variable
133 border-right: 1px solid @grey4;
128 border-right: 1px solid @grey4;
134 }
129 }
135
130
136 .pr_notifications {
131 .pr_notifications {
137 padding-left: .5em;
132 padding-left: .5em;
138 }
133 }
139
134
140 .pr_notifications + .menulabel {
135 .pr_notifications + .menulabel {
141 display:inline;
136 display:inline;
142 padding-left: 0;
137 padding-left: 0;
143 }
138 }
144
139
145 &:hover,
140 &:hover,
146 &.open,
141 &.open,
147 &.active {
142 &.active {
148 a {
143 a {
149 color: @grey1;
144 color: @grey1;
150 }
145 }
151 }
146 }
152 }
147 }
153
148
154 pre {
149 pre {
155 margin: 0;
150 margin: 0;
156 padding: 0;
151 padding: 0;
157 }
152 }
158
153
159 .select2-container,
154 .select2-container,
160 .menulink.childs {
155 .menulink.childs {
161 position: relative;
156 position: relative;
162 }
157 }
163
158
164 #quick_login {
159 #quick_login {
165
160
166 li a {
161 li a {
167 padding: .5em 0;
162 padding: .5em 0;
168 border-bottom: none;
163 border-bottom: none;
169 color: @grey2;
164 color: @grey2;
170
165
171 &:hover { color: @grey1; }
166 &:hover { color: @grey1; }
172 }
167 }
173
174 .show_more {
175 padding-left: .5em;
176 }
177 }
168 }
178
169
179 #quick_login_link {
170 #quick_login_link {
180 display: inline-block;
171 display: inline-block;
181
172
182 .gravatar {
173 .gravatar {
183 border: 1px solid @grey2;
174 border: 1px solid @grey5;
184 }
175 }
185
176
186 .gravatar-login {
177 .gravatar-login {
187 height: 20px;
178 height: 20px;
188 width: 20px;
179 width: 20px;
189 margin: -8px 0;
180 margin: -8px 0;
190 padding: 0;
181 padding: 0;
191 }
182 }
192
183
193 &:hover .user {
184 &:hover .user {
194 color: @grey6;
185 color: @grey6;
195 }
186 }
196 }
187 }
197 }
188 }
198 .header .horizontal-list {
189 .header .horizontal-list {
199
190
200 li {
191 li {
201
192
202 &#quick_login_li {
193 &#quick_login_li {
203 padding-left: .5em;
194 padding-left: .5em;
204
195
205 &:hover #quick_login_link {
196 &:hover #quick_login_link {
206 color: inherit;
197 color: inherit;
207 }
198 }
199
200 .menu_link_user {
201 padding: 0 2px;
202 }
208 }
203 }
209
204
210 &:before { content: none; }
205 &:before { content: none; }
211 }
206 }
212
207
213 > li {
208 > li {
214
209
215 a {
210 a {
216 padding: 18px 0 12px 0;
211 padding: 18px 0 12px 0;
217 color: @nav-grey;
212 color: @nav-grey;
218
213
219 &.menu_link_notifications {
214 &.menu_link_notifications {
220 padding: 1px 8px;
215 padding: 1px 8px;
221 }
216 }
222 }
217 }
223
218
224 &:hover,
219 &:hover,
225 &.open,
220 &.open,
226 &.active {
221 &.active {
227 .pill_container a {
222 .pill_container a {
228 // don't select text for the pill container, it has it' own
223 // don't select text for the pill container, it has it' own
229 // hover behaviour
224 // hover behaviour
230 color: @nav-grey;
225 color: @nav-grey;
231 }
226 }
232 }
227 }
233
228
234 &:hover,
229 &:hover,
235 &.open,
230 &.open,
236 &.active {
231 &.active {
237 a {
232 a {
238 color: @grey6;
233 color: @grey6;
239 }
234 }
240 }
235 }
241
236
242 .select2-dropdown-open a {
237 .select2-dropdown-open a {
243 color: @grey6;
238 color: @grey6;
244 }
239 }
245
240
246 .repo-switcher {
241 .repo-switcher {
247 padding-left: 0;
242 padding-left: 0;
248
243
249 .menulabel {
244 .menulabel {
250 padding-left: 0;
245 padding-left: 0;
251 }
246 }
252 }
247 }
253 }
248 }
254
249
255 li ul li {
250 li ul li {
256 background-color:@grey2;
251 background-color:@grey2;
257
252
258 a {
253 a {
259 padding: .5em 0;
254 padding: .5em 0;
260 border-bottom: @border-thickness solid @border-default-color;
255 border-bottom: @border-thickness solid @border-default-color;
261 color: @grey6;
256 color: @grey6;
262 }
257 }
263
258
264 &:last-child a, &.last a{
259 &:last-child a, &.last a{
265 border-bottom: none;
260 border-bottom: none;
266 }
261 }
267
262
268 &:hover {
263 &:hover {
269 background-color: @grey3;
264 background-color: @grey3;
270 }
265 }
271 }
266 }
272
267
273 .submenu {
268 .submenu {
274 margin-top: 5px;
269 margin-top: 5px;
275 }
270 }
276 }
271 }
277
272
278 // SUBMENUS
273 // SUBMENUS
279 .navigation .submenu {
274 .navigation .submenu {
280 display: none;
275 display: none;
281 }
276 }
282
277
283 .navigation li.open {
278 .navigation li.open {
284 .submenu {
279 .submenu {
285 display: block;
280 display: block;
286 }
281 }
287 }
282 }
288
283
289 .navigation li:last-child .submenu {
284 .navigation li:last-child .submenu {
290 right: -20px;
285 right: -20px;
291 left: auto;
286 left: auto;
292 }
287 }
293
288
294 .submenu {
289 .submenu {
295 position: absolute;
290 position: absolute;
296 top: 100%;
291 top: 100%;
297 left: 0;
292 left: 0;
298 min-width: 150px;
293 min-width: 150px;
299 margin: 6px 0 0;
294 margin: 6px 0 0;
300 padding: 0;
295 padding: 0;
301 text-align: left;
296 text-align: left;
302 font-family: @text-light;
297 font-family: @text-light;
303 border-radius: @border-radius;
298 border-radius: @border-radius;
304 z-index: 20;
299 z-index: 20;
305
300
306 li {
301 li {
307 display: block;
302 display: block;
308 margin: 0;
303 margin: 0;
309 padding: 0 .5em;
304 padding: 0 .5em;
310 line-height: 1em;
305 line-height: 1em;
311 color: @grey3;
306 color: @grey3;
312 background-color: @grey6;
307 background-color: @grey6;
313
308
314 &:before { content: none; }
309 &:before { content: none; }
315
310
316 a {
311 a {
317 display: block;
312 display: block;
318 width: 100%;
313 width: 100%;
319 padding: .5em 0;
314 padding: .5em 0;
320 border-right: none;
315 border-right: none;
321 border-bottom: @border-thickness solid white;
316 border-bottom: @border-thickness solid white;
322 color: @grey3;
317 color: @grey3;
323 }
318 }
324
319
325 ul {
320 ul {
326 display: none;
321 display: none;
327 position: absolute;
322 position: absolute;
328 top: 0;
323 top: 0;
329 right: 100%;
324 right: 100%;
330 padding: 0;
325 padding: 0;
331 z-index: 30;
326 z-index: 30;
332 }
327 }
333 &:hover {
328 &:hover {
334 background-color: @grey5;
329 background-color: @grey5;
335 -webkit-transition: background .3s;
330 -webkit-transition: background .3s;
336 -moz-transition: background .3s;
331 -moz-transition: background .3s;
337 -o-transition: background .3s;
332 -o-transition: background .3s;
338 transition: background .3s;
333 transition: background .3s;
339
334
340 ul {
335 ul {
341 display: block;
336 display: block;
342 }
337 }
343 }
338 }
344 }
339 }
345 }
340 }
346
341
347
342
348
343
349
344
350 // repo dropdown
345 // repo dropdown
351 .quick_repo_menu {
346 .quick_repo_menu {
352 width: 15px;
347 width: 15px;
353 text-align: center;
348 text-align: center;
354 position: relative;
349 position: relative;
355 cursor: pointer;
350 cursor: pointer;
356
351
357 div {
352 div {
358 overflow: visible !important;
353 overflow: visible !important;
359 }
354 }
360
355
361 &.sorting {
356 &.sorting {
362 cursor: auto;
357 cursor: auto;
363 }
358 }
364
359
365 &:hover {
360 &:hover {
366 .menu_items_container {
361 .menu_items_container {
367 position: absolute;
362 position: absolute;
368 display: block;
363 display: block;
369 }
364 }
370 .menu_items {
365 .menu_items {
371 display: block;
366 display: block;
372 }
367 }
373 }
368 }
374
369
375 i {
370 i {
376 margin: 0;
371 margin: 0;
377 color: @grey4;
372 color: @grey4;
378 }
373 }
379
374
380 .menu_items_container {
375 .menu_items_container {
381 position: absolute;
376 position: absolute;
382 top: 0;
377 top: 0;
383 left: 100%;
378 left: 100%;
384 margin: 0;
379 margin: 0;
385 padding: 0;
380 padding: 0;
386 list-style: none;
381 list-style: none;
387 background-color: @grey6;
382 background-color: @grey6;
388 z-index: 999;
383 z-index: 999;
389 text-align: left;
384 text-align: left;
390
385
391 a {
386 a {
392 color: @grey2;
387 color: @grey2;
393 }
388 }
394
389
395 ul.menu_items {
390 ul.menu_items {
396 margin: 0;
391 margin: 0;
397 padding: 0;
392 padding: 0;
398 }
393 }
399
394
400 li {
395 li {
401 margin: 0;
396 margin: 0;
402 padding: 0;
397 padding: 0;
403 line-height: 1em;
398 line-height: 1em;
404 list-style-type: none;
399 list-style-type: none;
405
400
406 &:before { content: none; }
401 &:before { content: none; }
407
402
408 a {
403 a {
409 display: block;
404 display: block;
410 height: 16px;
405 height: 16px;
411 padding: 8px; //must add up to td height (28px)
406 padding: 8px; //must add up to td height (28px)
412 width: 120px; // set width
407 width: 120px; // set width
413
408
414 &:hover {
409 &:hover {
415 background-color: @grey5;
410 background-color: @grey5;
416 -webkit-transition: background .3s;
411 -webkit-transition: background .3s;
417 -moz-transition: background .3s;
412 -moz-transition: background .3s;
418 -o-transition: background .3s;
413 -o-transition: background .3s;
419 transition: background .3s;
414 transition: background .3s;
420 }
415 }
421 }
416 }
422 }
417 }
423 }
418 }
424 }
419 }
425
420
426 // Header Repository Switcher
421 // Header Repository Switcher
427 // Select2 Dropdown
422 // Select2 Dropdown
428 #select2-drop.select2-drop.repo-switcher-dropdown {
423 #select2-drop.select2-drop.repo-switcher-dropdown {
429 width: auto !important;
424 width: auto !important;
430 margin-top: 5px;
425 margin-top: 5px;
431 padding: 1em 0;
426 padding: 1em 0;
432 text-align: left;
427 text-align: left;
433 .border-radius-bottom(@border-radius);
428 .border-radius-bottom(@border-radius);
434 border-color: transparent;
429 border-color: transparent;
435 color: @grey6;
430 color: @grey6;
436 background-color: @grey2;
431 background-color: @grey2;
437
432
438 input {
433 input {
439 min-width: 90%;
434 min-width: 90%;
440 }
435 }
441
436
442 ul.select2-result-sub {
437 ul.select2-result-sub {
443
438
444 li {
439 li {
445 line-height: 1em;
440 line-height: 1em;
446
441
447 &:hover,
442 &:hover,
448 &.select2-highlighted {
443 &.select2-highlighted {
449 background-color: @grey3;
444 background-color: @grey3;
450 }
445 }
451 }
446 }
452
447
453 &:before { content: none; }
448 &:before { content: none; }
454 }
449 }
455
450
456 ul.select2-results {
451 ul.select2-results {
457 min-width: 200px;
452 min-width: 200px;
458 margin: 0;
453 margin: 0;
459 padding: 0;
454 padding: 0;
460 list-style-type: none;
455 list-style-type: none;
461 overflow-x: visible;
456 overflow-x: visible;
462 overflow-y: scroll;
457 overflow-y: scroll;
463
458
464 li {
459 li {
465 padding: 0 8px;
460 padding: 0 8px;
466 line-height: 1em;
461 line-height: 1em;
467 color: @grey6;
462 color: @grey6;
468
463
469 &:before { content: none; }
464 &:before { content: none; }
470
465
471 &>.select2-result-label {
466 &>.select2-result-label {
472 padding: 8px 0;
467 padding: 8px 0;
473 border-bottom: @border-thickness solid @grey3;
468 border-bottom: @border-thickness solid @grey3;
474 white-space: nowrap;
469 white-space: nowrap;
475 color: @grey5;
470 color: @grey5;
476 cursor: pointer;
471 cursor: pointer;
477 }
472 }
478
473
479 &.select2-result-with-children {
474 &.select2-result-with-children {
480 margin: 0;
475 margin: 0;
481 padding: 0;
476 padding: 0;
482 }
477 }
483
478
484 &.select2-result-unselectable > .select2-result-label {
479 &.select2-result-unselectable > .select2-result-label {
485 margin: 0 8px;
480 margin: 0 8px;
486 }
481 }
487
482
488 }
483 }
489 }
484 }
490
485
491 ul.select2-result-sub {
486 ul.select2-result-sub {
492 margin: 0;
487 margin: 0;
493 padding: 0;
488 padding: 0;
494
489
495 li {
490 li {
496 display: block;
491 display: block;
497 margin: 0;
492 margin: 0;
498 border-right: none;
493 border-right: none;
499 line-height: 1em;
494 line-height: 1em;
500 font-family: @text-light;
495 font-family: @text-light;
501 color: @grey2;
496 color: @grey2;
502
497
503 &:before { content: none; }
498 &:before { content: none; }
504
499
505 &:hover {
500 &:hover {
506 background-color: @grey3;
501 background-color: @grey3;
507 }
502 }
508 }
503 }
509 }
504 }
510 }
505 }
511
506
512
507
513 #context-bar {
508 #context-bar {
514 display: block;
509 display: block;
515 margin: 0 auto;
510 margin: 0 auto;
516 padding: 0 @header-padding;
511 padding: 0 @header-padding;
517 background-color: @grey6;
512 background-color: @grey6;
518 border-bottom: @border-thickness solid @grey5;
513 border-bottom: @border-thickness solid @grey5;
519
514
520 .clear {
515 .clear {
521 clear: both;
516 clear: both;
522 }
517 }
523 }
518 }
524
519
525 ul#context-pages {
520 ul#context-pages {
526 li {
521 li {
527 line-height: 1em;
522 line-height: 1em;
528
523
529 &:before { content: none; }
524 &:before { content: none; }
530
525
531 a {
526 a {
532 color: @grey3;
527 color: @grey3;
533 }
528 }
534
529
535 &.active {
530 &.active {
536 // special case, non-variable color
531 // special case, non-variable color
537 border-bottom: 4px solid @nav-grey;
532 border-bottom: 4px solid @nav-grey;
538
533
539 a {
534 a {
540 color: @grey1;
535 color: @grey1;
541 }
536 }
542 }
537 }
543 }
538 }
544 }
539 }
545
540
546 // PAGINATION
541 // PAGINATION
547
542
548 .pagination {
543 .pagination {
549 border: @border-thickness solid @rcblue;
544 border: @border-thickness solid @rcblue;
550 color: @rcblue;
545 color: @rcblue;
551
546
552 .current {
547 .current {
553 color: @grey4;
548 color: @grey4;
554 }
549 }
555 }
550 }
556
551
557 .dataTables_processing {
552 .dataTables_processing {
558 text-align: center;
553 text-align: center;
559 font-size: 1.1em;
554 font-size: 1.1em;
560 position: relative;
555 position: relative;
561 top: 95px;
556 top: 95px;
562 }
557 }
563
558
564 .dataTables_paginate, .pagination-wh {
559 .dataTables_paginate, .pagination-wh {
565 text-align: left;
560 text-align: left;
566 display: inline-block;
561 display: inline-block;
567 border-left: 1px solid @rcblue;
562 border-left: 1px solid @rcblue;
568 float: none;
563 float: none;
569 overflow: hidden;
564 overflow: hidden;
570
565
571 .paginate_button, .pager_curpage,
566 .paginate_button, .pager_curpage,
572 .pager_link, .pg-previous, .pg-next, .pager_dotdot {
567 .pager_link, .pg-previous, .pg-next, .pager_dotdot {
573 display: inline-block;
568 display: inline-block;
574 padding: @menupadding/4 @menupadding;
569 padding: @menupadding/4 @menupadding;
575 border: 1px solid @rcblue;
570 border: 1px solid @rcblue;
576 border-left: 0;
571 border-left: 0;
577 color: @rcblue;
572 color: @rcblue;
578 cursor: pointer;
573 cursor: pointer;
579 float: left;
574 float: left;
580 }
575 }
581
576
582 .pager_curpage, .pager_dotdot,
577 .pager_curpage, .pager_dotdot,
583 .paginate_button.current, .paginate_button.disabled,
578 .paginate_button.current, .paginate_button.disabled,
584 .disabled {
579 .disabled {
585 color: @grey3;
580 color: @grey3;
586 cursor: default;
581 cursor: default;
587 }
582 }
588
583
589 .ellipsis {
584 .ellipsis {
590 display: inline-block;
585 display: inline-block;
591 text-align: left;
586 text-align: left;
592 padding: @menupadding/4 @menupadding;
587 padding: @menupadding/4 @menupadding;
593 border: 1px solid @rcblue;
588 border: 1px solid @rcblue;
594 border-left: 0;
589 border-left: 0;
595 float: left;
590 float: left;
596 }
591 }
597 }
592 }
598
593
599 // SIDEBAR
594 // SIDEBAR
600
595
601 .sidebar {
596 .sidebar {
602 .block-left;
597 .block-left;
603 clear: left;
598 clear: left;
604 max-width: @sidebar-width;
599 max-width: @sidebar-width;
605 margin-right: @sidebarpadding;
600 margin-right: @sidebarpadding;
606 padding-right: @sidebarpadding;
601 padding-right: @sidebarpadding;
607 font-family: @text-regular;
602 font-family: @text-regular;
608 color: @grey1;
603 color: @grey1;
609
604
610 &#graph_nodes {
605 &#graph_nodes {
611 clear:both;
606 clear:both;
612 width: auto;
607 width: auto;
613 margin-left: -100px;
608 margin-left: -100px;
614 padding: 0;
609 padding: 0;
615 border: none;
610 border: none;
616 }
611 }
617
612
618 .nav-pills {
613 .nav-pills {
619 margin: 0;
614 margin: 0;
620 }
615 }
621
616
622 .nav {
617 .nav {
623 list-style: none;
618 list-style: none;
624 padding: 0;
619 padding: 0;
625
620
626 li {
621 li {
627 padding-bottom: @menupadding;
622 padding-bottom: @menupadding;
628 line-height: 1em;
623 line-height: 1em;
629 color: @grey4;
624 color: @grey4;
630
625
631 &.active a {
626 &.active a {
632 color: @grey2;
627 color: @grey2;
633 }
628 }
634
629
635 a {
630 a {
636 color: @grey4;
631 color: @grey4;
637 }
632 }
638
633
639 &:before { content: none; }
634 &:before { content: none; }
640 }
635 }
641
636
642 }
637 }
643 }
638 }
644
639
645 .main_filter_help_box {
640 .main_filter_help_box {
646 padding: 7px 7px;
641 padding: 7px 7px;
647 border-top: 1px solid @grey4;
642 border-top: 1px solid @grey4;
648 border-right: 1px solid @grey4;
643 border-right: 1px solid @grey4;
649 border-bottom: 1px solid @grey4;
644 border-bottom: 1px solid @grey4;
650 display: inline-block;
645 display: inline-block;
651 vertical-align: top;
646 vertical-align: top;
652 margin-left: -5px;
647 margin-left: -7px;
653 background: @grey3;
648 background: @grey3;
654 }
649 }
655
650
656 .main_filter_input_box {
651 .main_filter_input_box {
657 display: inline-block;
652 display: inline-block;
658 }
653 }
659
654
660 .main_filter_box {
655 .main_filter_box {
661 margin: 9px 0 0 0;
656 margin: 9px 0 0 0;
662 }
657 }
663
658
664 #main_filter_help {
659 #main_filter_help {
665 background: @grey3;
660 background: @grey3;
666 border: 1px solid black;
661 border: 1px solid black;
667 position: absolute;
662 position: absolute;
668 white-space: pre-wrap;
663 white-space: pre-wrap;
669 z-index: 9999;
664 z-index: 9999;
670 color: @nav-grey;
665 color: @nav-grey;
671 margin: 1px 7px;
666 margin: 1px 7px;
672 padding: 0 2px;
667 padding: 0 2px;
673 }
668 }
674
669
675 .main_filter_input {
670 .main_filter_input {
676 padding: 6px;
671 padding: 5px;
677 min-width: 220px;
672 min-width: 220px;
678 color: @nav-grey;
673 color: @nav-grey;
679 background: @grey3;
674 background: @grey3;
675 min-height: 18px;
680 }
676 }
681
677
682 .main_filter_input::placeholder {
678 .main_filter_input::placeholder {
683 color: @nav-grey;
679 color: @nav-grey;
684 opacity: 1;
680 opacity: 1;
685 }
681 }
686
682
687 .notice-box {
683 .notice-box {
688 display:block !important;
684 display:block !important;
689 padding: 9px 0 !important;
685 padding: 9px 0 !important;
690 }
686 }
691
687
692 .menulabel-notice {
688 .menulabel-notice {
693 border: 1px solid @color5;
689 border: 1px solid @color5;
694 padding:7px 10px;
690 padding:7px 10px;
695 color: @color5;
691 color: @color5;
696 }
692 }
@@ -1,167 +1,170 b''
1 @font-face {
1 @font-face {
2 font-family: 'rcicons';
2 font-family: 'rcicons';
3 src: url('../fonts/RCIcons/rcicons.eot?74666722');
3 src: url('../fonts/RCIcons/rcicons.eot?74666722');
4 src: url('../fonts/RCIcons/rcicons.eot?74666722#iefix') format('embedded-opentype'),
4 src: url('../fonts/RCIcons/rcicons.eot?74666722#iefix') format('embedded-opentype'),
5 url('../fonts/RCIcons/rcicons.woff2?74666722') format('woff2'),
5 url('../fonts/RCIcons/rcicons.woff2?74666722') format('woff2'),
6 url('../fonts/RCIcons/rcicons.woff?74666722') format('woff'),
6 url('../fonts/RCIcons/rcicons.woff?74666722') format('woff'),
7 url('../fonts/RCIcons/rcicons.ttf?74666722') format('truetype'),
7 url('../fonts/RCIcons/rcicons.ttf?74666722') format('truetype'),
8 url('../fonts/RCIcons/rcicons.svg?74666722#rcicons') format('svg');
8 url('../fonts/RCIcons/rcicons.svg?74666722#rcicons') format('svg');
9 font-weight: normal;
9 font-weight: normal;
10 font-style: normal;
10 font-style: normal;
11 }
11 }
12 /* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
12 /* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
13 /* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
13 /* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
14 /*
14 /*
15 @media screen and (-webkit-min-device-pixel-ratio:0) {
15 @media screen and (-webkit-min-device-pixel-ratio:0) {
16 @font-face {
16 @font-face {
17 font-family: 'rcicons';
17 font-family: 'rcicons';
18 src: url('../fonts/RCIcons/rcicons.svg?74666722#rcicons') format('svg');
18 src: url('../fonts/RCIcons/rcicons.svg?74666722#rcicons') format('svg');
19 }
19 }
20 }
20 }
21 */
21 */
22
22
23 [class^="icon-"]:before, [class*=" icon-"]:before {
23 [class^="icon-"]:before, [class*=" icon-"]:before {
24 font-family: "rcicons";
24 font-family: "rcicons";
25 font-style: normal;
25 font-style: normal;
26 font-weight: normal;
26 font-weight: normal;
27 speak: none;
27 speak: none;
28
28
29 display: inline-block;
29 display: inline-block;
30 text-decoration: inherit;
30 text-decoration: inherit;
31 width: 1em;
31 width: 1em;
32 margin-right: .2em;
32 margin-right: .2em;
33 text-align: center;
33 text-align: center;
34 /* opacity: .8; */
34 /* opacity: .8; */
35
35
36 /* For safety - reset parent styles, that can break glyph codes*/
36 /* For safety - reset parent styles, that can break glyph codes*/
37 font-variant: normal;
37 font-variant: normal;
38 text-transform: none;
38 text-transform: none;
39
39
40 /* fix buttons height, for twitter bootstrap */
40 /* fix buttons height, for twitter bootstrap */
41 line-height: 1em;
41 line-height: 1em;
42
42
43 /* Animation center compensation - margins should be symmetric */
43 /* Animation center compensation - margins should be symmetric */
44 /* remove if not needed */
44 /* remove if not needed */
45 margin-left: .2em;
45 margin-left: .2em;
46
46
47 /* you can be more comfortable with increased icons size */
47 /* you can be more comfortable with increased icons size */
48 /* font-size: 120%; */
48 /* font-size: 120%; */
49
49
50 /* Font smoothing. That was taken from TWBS */
50 /* Font smoothing. That was taken from TWBS */
51 -webkit-font-smoothing: antialiased;
51 -webkit-font-smoothing: antialiased;
52 -moz-osx-font-smoothing: grayscale;
52 -moz-osx-font-smoothing: grayscale;
53
53
54 /* Uncomment for 3D effect */
54 /* Uncomment for 3D effect */
55 /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
55 /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
56 }
56 }
57
57
58 .icon-no-margin::before {
58 .icon-no-margin::before {
59 margin: 0;
59 margin: 0;
60
60
61 }
61 }
62 // -- ICON CLASSES -- //
62 // -- ICON CLASSES -- //
63
63
64 .icon-bookmark:before { content: '\e803'; } /* '' */
64 .icon-bookmark:before { content: '\e803'; } /* '' */
65 .icon-branch:before { content: '\e804'; } /* '' */
65 .icon-branch:before { content: '\e804'; } /* '' */
66 .icon-lock:before { content: '\e806'; } /* '' */
66 .icon-lock:before { content: '\e806'; } /* '' */
67 .icon-unlock:before { content: '\e807'; } /* '' */
67 .icon-unlock:before { content: '\e807'; } /* '' */
68 .icon-delete:before { content: '\e808'; } /* '' */
68 .icon-delete:before { content: '\e808'; } /* '' */
69 .icon-false:before { content: '\e808'; } /* '' */
69 .icon-false:before { content: '\e808'; } /* '' */
70
70
71 .icon-ok:before { content: '\e809'; } /* '' */
71 .icon-ok:before { content: '\e809'; } /* '' */
72 .icon-true:before { content: '\e809'; } /* '' */
72 .icon-true:before { content: '\e809'; } /* '' */
73
73
74 .icon-comment:before { content: '\e80a'; } /* '' */
74 .icon-comment:before { content: '\e80a'; } /* '' */
75 .icon-comment-add:before { content: '\e816'; } /* '' */
75 .icon-comment-add:before { content: '\e816'; } /* '' */
76 .icon-comment_toggle:before { content: '\e818'; } /* '' */
76 .icon-comment_toggle:before { content: '\e818'; } /* '' */
77
77
78 .icon-feed:before { content: '\e80b'; } /* '' */
78 .icon-feed:before { content: '\e80b'; } /* '' */
79
79
80 .icon-right:before { content: '\e80c'; } /* '' */
80 .icon-right:before { content: '\e80c'; } /* '' */
81 .icon-left:before { content: '\e80d'; } /* '' */
81 .icon-left:before { content: '\e80d'; } /* '' */
82
82
83 .icon-arrow_down:before { content: '\e80e'; } /* '' */
83 .icon-arrow_down:before { content: '\e80e'; } /* '' */
84 .icon-arrow_up:before { content: '\e80e'; } /* '' */
84 .icon-arrow_up:before { content: '\e80e'; } /* '' */
85
85
86 .icon-group:before { content: '\e812'; } /* '' */
86 .icon-group:before { content: '\e812'; } /* '' */
87
87
88 .icon-fork:before { content: '\e814'; } /* '' */
88 .icon-fork:before { content: '\e814'; } /* '' */
89 .icon-merge:before { content: '\e814'; } /* '' */
89 .icon-merge:before { content: '\e814'; } /* '' */
90
90
91 .icon-more:before { content: '\e815'; } /* '' */
91 .icon-more:before { content: '\e815'; } /* '' */
92
92
93 .icon-more-linked { cursor: pointer; color: @grey3 }
94 .icon-more-linked:before { content: '\e815'; } /* '' */
95
93 .icon-git-inv:before { content: '\e80f'; } /* '' */
96 .icon-git-inv:before { content: '\e80f'; } /* '' */
94 .icon-hg-inv:before { content: '\e810'; } /* '' */
97 .icon-hg-inv:before { content: '\e810'; } /* '' */
95 .icon-svn-inv:before { content: '\e811'; } /* '' */
98 .icon-svn-inv:before { content: '\e811'; } /* '' */
96
99
97 .icon-git:before { content: '\e81a'; } /* '' */
100 .icon-git:before { content: '\e81a'; } /* '' */
98 .icon-hg:before { content: '\e81b'; } /* '' */
101 .icon-hg:before { content: '\e81b'; } /* '' */
99 .icon-svn:before { content: '\e820'; } /* '' */
102 .icon-svn:before { content: '\e820'; } /* '' */
100
103
101 .icon-minus:before { content: '\e81c'; } /* '' */
104 .icon-minus:before { content: '\e81c'; } /* '' */
102 .icon-plus:before { content: '\e81d'; } /* '' */
105 .icon-plus:before { content: '\e81d'; } /* '' */
103 .icon-remove:before { content: '\e81e'; } /* '' */
106 .icon-remove:before { content: '\e81e'; } /* '' */
104 .icon-remove-sign:before { content: '\e81e'; } /* '' */
107 .icon-remove-sign:before { content: '\e81e'; } /* '' */
105
108
106 .icon-rhodecode:before { content: '\e81f'; } /* '' */
109 .icon-rhodecode:before { content: '\e81f'; } /* '' */
107
110
108 .icon-tag:before { content: '\e821'; } /* '' */
111 .icon-tag:before { content: '\e821'; } /* '' */
109 .icon-copy:before { content: '\f0c5'; } /* '' */
112 .icon-copy:before { content: '\f0c5'; } /* '' */
110 .icon-clipboard:before { content: '\f0c5'; } /* '' */
113 .icon-clipboard:before { content: '\f0c5'; } /* '' */
111
114
112
115
113 .icon-folder:before { content: '\e813'; } /* '' */
116 .icon-folder:before { content: '\e813'; } /* '' */
114 .icon-folder-close:before { content: '\e813'; } /* '' */
117 .icon-folder-close:before { content: '\e813'; } /* '' */
115
118
116 .icon-directory:before { content: '\e800'; } /* '' */
119 .icon-directory:before { content: '\e800'; } /* '' */
117 .icon-directory-empty:before { content: '\f114'; } /* '' */
120 .icon-directory-empty:before { content: '\f114'; } /* '' */
118 .icon-file-text:before { content: '\f0f6'; } /* '' */
121 .icon-file-text:before { content: '\f0f6'; } /* '' */
119 .icon-file-text-inv:before { content: '\f15c'; } /* '' */
122 .icon-file-text-inv:before { content: '\f15c'; } /* '' */
120 .icon-file-code:before { content: '\f1c9'; } /* '' */
123 .icon-file-code:before { content: '\f1c9'; } /* '' */
121
124
122 // MERGED ICONS
125 // MERGED ICONS
123
126
124 .icon-repo-private:before { &:extend(.icon-lock:before); }
127 .icon-repo-private:before { &:extend(.icon-lock:before); }
125 .icon-repo-lock:before { &:extend(.icon-lock:before); }
128 .icon-repo-lock:before { &:extend(.icon-lock:before); }
126 .icon-unlock-alt:before { &:extend(.icon-unlock:before); }
129 .icon-unlock-alt:before { &:extend(.icon-unlock:before); }
127 .icon-repo-unlock:before { &:extend(.icon-unlock:before); }
130 .icon-repo-unlock:before { &:extend(.icon-unlock:before); }
128 .icon-repo-public:before { &:extend(.icon-unlock:before); }
131 .icon-repo-public:before { &:extend(.icon-unlock:before); }
129 .icon-rss-sign:before { &:extend(.icon-feed:before); }
132 .icon-rss-sign:before { &:extend(.icon-feed:before); }
130 .icon-code-fork:before { &:extend(.icon-fork:before); }
133 .icon-code-fork:before { &:extend(.icon-fork:before); }
131
134
132 // TRANSFORM
135 // TRANSFORM
133 .icon-arrow_up:before {transform: rotate(180deg);}
136 .icon-arrow_up:before {transform: rotate(180deg);}
134 .icon-merge:before {transform: rotate(180deg);}
137 .icon-merge:before {transform: rotate(180deg);}
135
138
136 // -- END ICON CLASSES -- //
139 // -- END ICON CLASSES -- //
137
140
138
141
139 //--- ICONS STYLING ------------------//
142 //--- ICONS STYLING ------------------//
140
143
141 .icon-git { color: @color4 !important; }
144 .icon-git { color: @color4 !important; }
142 .icon-hg { color: @color8 !important; }
145 .icon-hg { color: @color8 !important; }
143 .icon-svn { color: @color1 !important; }
146 .icon-svn { color: @color1 !important; }
144 .icon-git-inv { color: @color4 !important; }
147 .icon-git-inv { color: @color4 !important; }
145 .icon-hg-inv { color: @color8 !important; }
148 .icon-hg-inv { color: @color8 !important; }
146 .icon-svn-inv { color: @color1 !important; }
149 .icon-svn-inv { color: @color1 !important; }
147 .icon-repo-lock { color: #FF0000; }
150 .icon-repo-lock { color: #FF0000; }
148 .icon-repo-unlock { color: #FF0000; }
151 .icon-repo-unlock { color: #FF0000; }
149
152
150 .repo-switcher-dropdown .select2-result-label {
153 .repo-switcher-dropdown .select2-result-label {
151 .icon-git:before {
154 .icon-git:before {
152 &:extend(.icon-git-transparent:before);
155 &:extend(.icon-git-transparent:before);
153 }
156 }
154 .icon-hg:before {
157 .icon-hg:before {
155 &:extend(.icon-hg-transparent:before);
158 &:extend(.icon-hg-transparent:before);
156 color: @alert4;
159 color: @alert4;
157 }
160 }
158 .icon-svn:before {
161 .icon-svn:before {
159 &:extend(.icon-svn-transparent:before);
162 &:extend(.icon-svn-transparent:before);
160 }
163 }
161 }
164 }
162
165
163 .icon-user-group:before {
166 .icon-user-group:before {
164 &:extend(.icon-group:before);
167 &:extend(.icon-group:before);
165 margin: 0;
168 margin: 0;
166 font-size: 16px;
169 font-size: 16px;
167 }
170 }
@@ -1,222 +1,222 b''
1 // select2.less
1 // select2.less
2 // For use in RhodeCode application drop down select boxes;
2 // For use in RhodeCode application drop down select boxes;
3 // see style guide documentation for guidelines.
3 // see style guide documentation for guidelines.
4
4
5
5
6 // SELECT2 DROPDOWN MENUS
6 // SELECT2 DROPDOWN MENUS
7
7
8 //Select2 Dropdown
8 //Select2 Dropdown
9 .select2-results{
9 .select2-results{
10 .box-sizing(border-box);
10 .box-sizing(border-box);
11 overflow-y: scroll;
11 overflow-y: scroll;
12 }
12 }
13
13
14 .select2-container{margin: 0; position: relative; display: inline-block; zoom: 1;}
14 .select2-container{margin: 0; position: relative; display: inline-block; zoom: 1;}
15 .select2-container,
15 .select2-container,
16 .select2-drop,
16 .select2-drop,
17 .select2-search,
17 .select2-search,
18 .select2-search input {.box-sizing(border-box);}
18 .select2-search input {.box-sizing(border-box);}
19 .select2-container .select2-choice{display:block; line-height:1em; -webkit-touch-callout:none;-moz-user-select:none;-ms-user-select:none;user-select:none; }
19 .select2-container .select2-choice{display:block; line-height:1em; -webkit-touch-callout:none;-moz-user-select:none;-ms-user-select:none;user-select:none; }
20 .main .select2-container .select2-choice { background-color: white; }
20 .main .select2-container .select2-choice { background-color: white; }
21 .select2-container .select2-choice abbr { display: none; width: 12px; height: 12px; position: absolute; right: 24px; top: 8px; font-size: 1px; text-decoration: none; border: 0; background: url('../images/select2.png') right top no-repeat; cursor: pointer; outline: 0; }
21 .select2-container .select2-choice abbr { display: none; width: 12px; height: 12px; position: absolute; right: 24px; top: 8px; font-size: 1px; text-decoration: none; border: 0; background: url('../images/select2.png') right top no-repeat; cursor: pointer; outline: 0; }
22 .select2-container.select2-allowclear .select2-choice abbr {display: inline-block;}
22 .select2-container.select2-allowclear .select2-choice abbr {display: inline-block;}
23 .select2-container .select2-choice abbr:hover { background-position: right -11px; cursor: pointer; }
23 .select2-container .select2-choice abbr:hover { background-position: right -11px; cursor: pointer; }
24 .select2-drop-mask { border: 0; margin: 0; padding: 0; position: fixed; left: 0; top: 0; min-height: 100%; min-width: 100%; height: auto; width: auto; opacity: 0; z-index: 998; background-color: #fff; filter: alpha(opacity=0); }
24 .select2-drop-mask { border: 0; margin: 0; padding: 0; position: fixed; left: 0; top: 0; min-height: 100%; min-width: 100%; height: auto; width: auto; opacity: 0; z-index: 998; background-color: #fff; filter: alpha(opacity=0); }
25 .select2-drop { width: 100%; margin-top: -1px; position: absolute; z-index: 999; top: 100%; background: #fff; color: #000; border: @border-thickness solid @rcblue; border-top: 0; border-radius: 0 0 @border-radius @border-radius; }
25 .select2-drop { width: 100%; margin-top: -1px; position: absolute; z-index: 999; top: 100%; background: #fff; color: #000; border: @border-thickness solid @rcblue; border-top: 0; border-radius: 0 0 @border-radius @border-radius; }
26 .select2-drop.select2-drop-above { margin-top: 1px; border-top: @border-thickness solid @rclightblue; border-bottom: 0; border-radius: @border-radius @border-radius 0 0; }
26 .select2-drop.select2-drop-above { margin-top: 1px; border-top: @border-thickness solid @rclightblue; border-bottom: 0; border-radius: @border-radius @border-radius 0 0; }
27 .select2-drop-active { border: @border-thickness solid #5897fb; border-top: none; }
27 .select2-drop-active { border: @border-thickness solid #5897fb; border-top: none; }
28 .select2-drop.select2-drop-above.select2-drop-active {border-top: @border-thickness solid #5897fb;}
28 .select2-drop.select2-drop-above.select2-drop-active {border-top: @border-thickness solid #5897fb;}
29 .select2-drop-auto-width { border-top: @border-thickness solid #aaa; width: auto; }
29 .select2-drop-auto-width { border-top: @border-thickness solid #aaa; width: auto; }
30 .select2-drop-auto-width .select2-search {padding-top: 4px;}
30 .select2-drop-auto-width .select2-search {padding-top: 4px;}
31 html[dir="rtl"] .select2-container .select2-choice .select2-arrow { left: 0; right: auto; border-left: none; border-right: @border-thickness solid @grey5; border-radius: @border-radius 0 0 @border-radius; }
31 html[dir="rtl"] .select2-container .select2-choice .select2-arrow { left: 0; right: auto; border-left: none; border-right: @border-thickness solid @grey5; border-radius: @border-radius 0 0 @border-radius; }
32 html[dir="rtl"] .select2-container .select2-choice .select2-arrow b {background-position: 2px 1px;}
32 html[dir="rtl"] .select2-container .select2-choice .select2-arrow b {background-position: 2px 1px;}
33 .select2-search { display: inline-block; width: 100%; min-height: 26px; margin: 0; padding-left: 4px; padding-right: 4px; position: relative; z-index: 1000; white-space: nowrap; }
33 .select2-search { display: inline-block; width: 100%; min-height: 26px; margin: 0; padding-left: 4px; padding-right: 4px; position: relative; z-index: 1000; white-space: nowrap; }
34 .select2-search input { width: 100%; height: auto !important; min-height: 26px; padding: 4px 20px 4px 5px; margin: 0; outline: 0; }
34 .select2-search input { width: 100%; height: auto !important; min-height: 26px; padding: 4px 20px 4px 5px; margin: 0; outline: 0; }
35 html[dir="rtl"] .select2-search input { padding: 4px 5px 4px 20px; background: #fff url('../images/select2.png') no-repeat -37px -22px; }
35 html[dir="rtl"] .select2-search input { padding: 4px 5px 4px 20px; background: #fff url('../images/select2.png') no-repeat -37px -22px; }
36 .select2-drop.select2-drop-above .select2-search input {margin-top: 4px;}
36 .select2-drop.select2-drop-above .select2-search input {margin-top: 4px;}
37 .select2-dropdown-open .select2-choice .select2-arrow { background: transparent; border-left: none; filter: none; }
37 .select2-dropdown-open .select2-choice .select2-arrow { background: transparent; border-left: none; filter: none; }
38 html[dir="rtl"] .select2-dropdown-open .select2-choice .select2-arrow {border-right: none;}
38 html[dir="rtl"] .select2-dropdown-open .select2-choice .select2-arrow {border-right: none;}
39 .select2-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
39 .select2-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
40 /* results */
40 /* results */
41 .select2-results { max-height: 200px; padding: 0 0 0 4px; margin: 4px 4px 4px 0; position: relative; overflow-x: hidden; overflow-y: auto; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); }
41 .select2-results { max-height: 200px; padding: 0 0 0 4px; margin: 4px 4px 4px 0; position: relative; overflow-x: hidden; overflow-y: auto; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); }
42 html[dir="rtl"] .select2-results { padding: 0 4px 0 0; margin: 4px 0 4px 4px; }
42 html[dir="rtl"] .select2-results { padding: 0 4px 0 0; margin: 4px 0 4px 4px; }
43 .select2-results .select2-disabled{background:@grey6;display:list-item;cursor:default}
43 .select2-results .select2-disabled{background:@grey6;display:list-item;cursor:default}
44 .select2-results .select2-selected{display:none}
44 .select2-results .select2-selected{display:none}
45 .select2-more-results.select2-active{background:#f4f4f4 url('../images/select2-spinner.gif') no-repeat 100%}
45 .select2-more-results.select2-active{background:#f4f4f4 url('../images/select2-spinner.gif') no-repeat 100%}
46 .select2-container.select2-container-disabled .select2-choice abbr{display:none}
46 .select2-container.select2-container-disabled .select2-choice abbr{display:none}
47 .select2-container.select2-container-disabled {background:@grey6;cursor:default}
47 .select2-container.select2-container-disabled {background:@grey6;cursor:default}
48 .select2-container.select2-container-disabled .select2-choice {background:@grey6;cursor:default}
48 .select2-container.select2-container-disabled .select2-choice {background:@grey6;cursor:default}
49 .select2-container-multi .select2-choices li{float:left;list-style:none}
49 .select2-container-multi .select2-choices li{float:left;list-style:none}
50 .select2-container-multi .select2-choices .select2-search-field{margin:0;padding:0;white-space:nowrap}
50 .select2-container-multi .select2-choices .select2-search-field{margin:0;padding:0;white-space:nowrap}
51 .select2-container-multi .select2-choices .select2-search-choice .select2-chosen{cursor:default}
51 .select2-container-multi .select2-choices .select2-search-choice .select2-chosen{cursor:default}
52 .select2-search-choice-close{display:block;width:12px;height:13px;position:absolute;right:3px;top:4px;font-size:1px;outline:none;background:url('../images/select2.png') right top no-repeat}
52 .select2-search-choice-close{display:block;width:12px;height:13px;position:absolute;right:3px;top:4px;font-size:1px;outline:none;background:url('../images/select2.png') right top no-repeat}
53 .select2-container-multi .select2-search-choice-close{left:3px}
53 .select2-container-multi .select2-search-choice-close{left:3px}
54 .select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover{background-position:right -11px}
54 .select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover{background-position:right -11px}
55 .select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close{background-position:right -11px}
55 .select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close{background-position:right -11px}
56 .select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close{display:none;background:none}
56 .select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close{display:none;background:none}
57 .select2-offscreen,.select2-offscreen:focus{clip:rect(0 0 0 0) !important;width:1px !important;height:1px !important;
57 .select2-offscreen,.select2-offscreen:focus{clip:rect(0 0 0 0) !important;width:1px !important;height:1px !important;
58 border:0 !important;margin:0 !important;padding:0 !important;overflow:hidden !important;
58 border:0 !important;margin:0 !important;padding:0 !important;overflow:hidden !important;
59 position: absolute !important;outline:0 !important;left:0 !important;top:0 !important}
59 position: absolute !important;outline:0 !important;left:0 !important;top:0 !important}
60 .select2-display-none,
60 .select2-display-none,
61 .select2-search-hidden {display:none}
61 .select2-search-hidden {display:none}
62 .select2-search input { border-color: @rclightblue; }
62 .select2-search input { border-color: @rclightblue; }
63
63
64 .select2-measure-scrollbar{position:absolute;top:-10000px;left:-10000px;width:100px;height:100px;overflow:scroll}
64 .select2-measure-scrollbar{position:absolute;top:-10000px;left:-10000px;width:100px;height:100px;overflow:scroll}
65 @media only screen and (-webkit-min-device-pixel-ratio:1.5),
65 @media only screen and (-webkit-min-device-pixel-ratio:1.5),
66 only screen and (min-resolution:144dpi){
66 only screen and (min-resolution:144dpi){
67 .select2-search input,
67 .select2-search input,
68 .select2-search-choice-close,
68 .select2-search-choice-close,
69 .select2-container .select2-choice abbr,
69 .select2-container .select2-choice abbr,
70 .select2-container .select2-choice .select2-arrow b{background-image:url('../images/select2x2.png');background-repeat:no-repeat;background-size:60px 40px;}
70 .select2-container .select2-choice .select2-arrow b{background-image:url('../images/select2x2.png');background-repeat:no-repeat;background-size:60px 40px;}
71 .select2-search input{background-position:100% -21px}
71 .select2-search input{background-position:100% -21px}
72 }
72 }
73 [class^="input-"] [class^="select2-choice"]>div{display:none}
73 [class^="input-"] [class^="select2-choice"]>div{display:none}
74 [class^="input-"] .select2-offscreen{position:absolute}
74 [class^="input-"] .select2-offscreen{position:absolute}
75 select.select2{height:28px;visibility:hidden}
75 select.select2{height:28px;visibility:hidden}
76 .autocomplete-suggestions{overflow:auto}
76 .autocomplete-suggestions{overflow:auto}
77 .autocomplete-suggestion{white-space:nowrap;overflow:hidden}
77 .autocomplete-suggestion{white-space:nowrap;overflow:hidden}
78
78
79 /* Retina-ize icons */
79 /* Retina-ize icons */
80 @media only screen and (-webkit-min-device-pixel-ratio:1.5),
80 @media only screen and (-webkit-min-device-pixel-ratio:1.5),
81 only screen and (min-resolution:144dpi){
81 only screen and (min-resolution:144dpi){
82 .select2-search input,
82 .select2-search input,
83 .select2-search-choice-close,
83 .select2-search-choice-close,
84 .select2-container .select2-choice abbr,
84 .select2-container .select2-choice abbr,
85 .select2-container .select2-choice .select2-arrow b{background-image:url('../images/select2x2.png');background-repeat:no-repeat;background-size:60px 40px;}
85 .select2-container .select2-choice .select2-arrow b{background-image:url('../images/select2x2.png');background-repeat:no-repeat;background-size:60px 40px;}
86 .select2-search input{background-position:100% -21px}
86 .select2-search input{background-position:100% -21px}
87 }
87 }
88
88
89 //Internal Select2 Dropdown Menus
89 //Internal Select2 Dropdown Menus
90
90
91 .drop-menu-core {
91 .drop-menu-core {
92 min-width: 160px;
92 min-width: 160px;
93 margin: 0 @padding 0 0;
93 margin: 0 @padding 0 0;
94 padding: 0;
94 padding: 0;
95 border: @border-thickness solid @rcblue;
95 border: @border-thickness solid @rcblue;
96 border-radius: @border-radius;
96 border-radius: @border-radius;
97 color: @rcblue;
97 color: @rcblue;
98 background-color: white;
98 background-color: white;
99 }
99 }
100
100
101 .drop-menu-dropdown {
101 .drop-menu-dropdown {
102 .drop-menu-core;
102 .drop-menu-core;
103
103
104 .flag_status {
104 .flag_status {
105 margin-top: 0;
105 margin-top: 0;
106 }
106 }
107 }
107 }
108
108
109 .drop-menu-base {
109 .drop-menu-base {
110 .drop-menu-core;
110 .drop-menu-core;
111 position: relative;
111 position: relative;
112 display: inline-block;
112 display: inline-block;
113 line-height: 1em;
113 line-height: 1em;
114 z-index: 2;
114 z-index: 2;
115 cursor: pointer;
115 cursor: pointer;
116
116
117 .flag_status {
117 .flag_status {
118 margin-top: 0;
118 margin-top: 0;
119 }
119 }
120
120
121 a {
121 a {
122 display:block;
122 display:block;
123 padding: .9em;
123 padding: .9em;
124 padding-right: 2em;
124 padding-right: 2em;
125 position: relative;
125 position: relative;
126
126
127 &:after {
127 &:after {
128 position: absolute;
128 position: absolute;
129 content: "\00A0\25BE";
129 content: "\00A0\25BE";
130 right: .6em;
130 right: .1em;
131 line-height: 1em;
131 line-height: 1em;
132 top: 0.9em;
132 top: 0.4em;
133 width: 1em;
133 width: 1em;
134 font-size: 1em;
134 font-size: 20px;
135 }
135 }
136 }
136 }
137 }
137 }
138
138
139 .drop-menu {
139 .drop-menu {
140 .drop-menu-base;
140 .drop-menu-base;
141 width: auto !important;
141 width: auto !important;
142 }
142 }
143
143
144 .drop-menu-no-width {
144 .drop-menu-no-width {
145 .drop-menu-base;
145 .drop-menu-base;
146 width: auto;
146 width: auto;
147 }
147 }
148
148
149 .field-sm .drop-menu {
149 .field-sm .drop-menu {
150 padding: 1px 0 0 0;
150 padding: 1px 0 0 0;
151 a {
151 a {
152 padding: 6px;
152 padding: 6px;
153 };
153 };
154 }
154 }
155
155
156 .select2-search input {
156 .select2-search input {
157 width: 100%;
157 width: 100%;
158 margin: .5em 0;
158 margin: .5em 0;
159 padding: .5em;
159 padding: .5em;
160 }
160 }
161
161
162 .select2-no-results {
162 .select2-no-results {
163 padding: .5em;
163 padding: .5em;
164 }
164 }
165
165
166 .drop-menu-dropdown ul {
166 .drop-menu-dropdown ul {
167 width: auto;
167 width: auto;
168 margin: 0;
168 margin: 0;
169 padding: 0;
169 padding: 0;
170 z-index: 50;
170 z-index: 50;
171
171
172 li {
172 li {
173 margin: 0;
173 margin: 0;
174 line-height: 1em;
174 line-height: 1em;
175 list-style-type: none;
175 list-style-type: none;
176
176
177 &:before { content: none; }
177 &:before { content: none; }
178
178
179 &:hover,
179 &:hover,
180 &.select2-highlighted {
180 &.select2-highlighted {
181 background-color: @rclightblue;
181 background-color: @rclightblue;
182 }
182 }
183
183
184 &.select2-result-with-children {
184 &.select2-result-with-children {
185 &:hover {
185 &:hover {
186 background-color: white;
186 background-color: white;
187 }
187 }
188 }
188 }
189
189
190 .select2-result-label {
190 .select2-result-label {
191 display:block;
191 display:block;
192 padding: 8px;
192 padding: 8px;
193 font-family: @text-regular;
193 font-family: @text-regular;
194 border-bottom: @border-thickness solid @rclightblue;
194 border-bottom: @border-thickness solid @rclightblue;
195 color: @rcblue;
195 color: @rcblue;
196 cursor: pointer;
196 cursor: pointer;
197 }
197 }
198 &.select2-result-with-children {
198 &.select2-result-with-children {
199
199
200 .select2-result-label {
200 .select2-result-label {
201 font-family: @text-semibold;
201 font-family: @text-semibold;
202 color: @rcdarkblue;
202 color: @rcdarkblue;
203 cursor: default;
203 cursor: default;
204 }
204 }
205
205
206 ul.select2-result-sub li .select2-result-label {
206 ul.select2-result-sub li .select2-result-label {
207 padding-left: 16px;
207 padding-left: 16px;
208 font-family: @text-regular;
208 font-family: @text-regular;
209 color: @rcblue;
209 color: @rcblue;
210 cursor: pointer;
210 cursor: pointer;
211 }
211 }
212 }
212 }
213 }
213 }
214 }
214 }
215
215
216 .side-by-side-selector {
216 .side-by-side-selector {
217 .left-group,
217 .left-group,
218 .middle-group,
218 .middle-group,
219 .right-group {
219 .right-group {
220 margin-bottom: @padding;
220 margin-bottom: @padding;
221 }
221 }
222 }
222 }
@@ -1,545 +1,545 b''
1 //
1 //
2 // Typography
2 // Typography
3 // modified from Bootstrap
3 // modified from Bootstrap
4 // --------------------------------------------------
4 // --------------------------------------------------
5
5
6 // Base
6 // Base
7 body {
7 body {
8 font-size: @basefontsize;
8 font-size: @basefontsize;
9 font-family: @text-light;
9 font-family: @text-light;
10 letter-spacing: .02em;
10 letter-spacing: .02em;
11 color: @grey2;
11 color: @grey2;
12 }
12 }
13
13
14 #content, label{
14 #content, label{
15 font-size: @basefontsize;
15 font-size: @basefontsize;
16 }
16 }
17
17
18 label {
18 label {
19 color: @grey2;
19 color: @grey2;
20 }
20 }
21
21
22 ::selection { background: @rchighlightblue; }
22 ::selection { background: @rchighlightblue; }
23
23
24 // Headings
24 // Headings
25 // -------------------------
25 // -------------------------
26
26
27 h1, h2, h3, h4, h5, h6,
27 h1, h2, h3, h4, h5, h6,
28 .h1, .h2, .h3, .h4, .h5, .h6 {
28 .h1, .h2, .h3, .h4, .h5, .h6 {
29 margin: 0 0 @textmargin 0;
29 margin: 0 0 @textmargin 0;
30 padding: 0;
30 padding: 0;
31 line-height: 1.8em;
31 line-height: 1.8em;
32 color: @text-color;
32 color: @text-color;
33 a {
33 a {
34 color: @rcblue;
34 color: @rcblue;
35 }
35 }
36 }
36 }
37
37
38 h1, .h1 { font-size: 1.54em; font-family: @text-bold; }
38 h1, .h1 { font-size: 1.54em; font-family: @text-bold; }
39 h2, .h2 { font-size: 1.23em; font-family: @text-semibold; }
39 h2, .h2 { font-size: 1.23em; font-family: @text-semibold; }
40 h3, .h3 { font-size: 1.23em; font-family: @text-regular; }
40 h3, .h3 { font-size: 1.23em; font-family: @text-regular; }
41 h4, .h4 { font-size: 1em; font-family: @text-bold; }
41 h4, .h4 { font-size: 1em; font-family: @text-bold; }
42 h5, .h5 { font-size: 1em; font-family: @text-bold-italic; }
42 h5, .h5 { font-size: 1em; font-family: @text-bold-italic; }
43 h6, .h6 { font-size: 1em; font-family: @text-bold-italic; }
43 h6, .h6 { font-size: 1em; font-family: @text-bold-italic; }
44
44
45 // Breadcrumbs
45 // Breadcrumbs
46 .breadcrumbs {
46 .breadcrumbs {
47 &:extend(h1);
47 font-size: @repo-title-fontsize;
48 margin: 0;
48 margin: 0;
49 }
49 }
50
50
51 .breadcrumbs_light {
51 .breadcrumbs_light {
52 float:left;
52 float:left;
53 font-size: 1.3em;
53 font-size: 1.3em;
54 line-height: 38px;
54 line-height: 38px;
55 }
55 }
56
56
57 // Body text
57 // Body text
58 // -------------------------
58 // -------------------------
59
59
60 p {
60 p {
61 margin: 0 0 @textmargin 0;
61 margin: 0 0 @textmargin 0;
62 padding: 0;
62 padding: 0;
63 line-height: 2em;
63 line-height: 2em;
64 }
64 }
65
65
66 .lead {
66 .lead {
67 margin-bottom: @textmargin;
67 margin-bottom: @textmargin;
68 font-weight: 300;
68 font-weight: 300;
69 line-height: 1.4;
69 line-height: 1.4;
70
70
71 @media (min-width: @screen-sm-min) {
71 @media (min-width: @screen-sm-min) {
72 font-size: (@basefontsize * 1.5);
72 font-size: (@basefontsize * 1.5);
73 }
73 }
74 }
74 }
75
75
76 a,
76 a,
77 .link {
77 .link {
78 color: @rcblue;
78 color: @rcblue;
79 text-decoration: none;
79 text-decoration: none;
80 outline: none;
80 outline: none;
81 cursor: pointer;
81 cursor: pointer;
82
82
83 &:focus {
83 &:focus {
84 outline: none;
84 outline: none;
85 }
85 }
86
86
87 &:hover {
87 &:hover {
88 color: @rcdarkblue;
88 color: @rcdarkblue;
89 }
89 }
90 }
90 }
91
91
92 img {
92 img {
93 border: none;
93 border: none;
94 outline: none;
94 outline: none;
95 }
95 }
96
96
97 strong {
97 strong {
98 font-family: @text-bold;
98 font-family: @text-bold;
99 }
99 }
100
100
101 em {
101 em {
102 font-family: @text-italic;
102 font-family: @text-italic;
103 }
103 }
104
104
105 strong em,
105 strong em,
106 em strong {
106 em strong {
107 font-family: @text-bold-italic;
107 font-family: @text-bold-italic;
108 }
108 }
109
109
110 //TODO: lisa: b and i are depreciated, but we are still using them in places.
110 //TODO: lisa: b and i are depreciated, but we are still using them in places.
111 // Should probably make some decision whether to keep or lose these.
111 // Should probably make some decision whether to keep or lose these.
112 b {
112 b {
113
113
114 }
114 }
115
115
116 i {
116 i {
117 font-style: normal;
117 font-style: normal;
118 }
118 }
119
119
120 label {
120 label {
121 color: @text-color;
121 color: @text-color;
122
122
123 input[type="checkbox"] {
123 input[type="checkbox"] {
124 margin-right: 1em;
124 margin-right: 1em;
125 }
125 }
126 input[type="radio"] {
126 input[type="radio"] {
127 margin-right: 1em;
127 margin-right: 1em;
128 }
128 }
129 }
129 }
130
130
131 code,
131 code,
132 .code {
132 .code {
133 font-size: .95em;
133 font-size: .95em;
134 font-family: @text-code;
134 font-family: @text-code;
135 color: @grey3;
135 color: @grey3;
136
136
137 a {
137 a {
138 color: lighten(@rcblue,10%)
138 color: lighten(@rcblue,10%)
139 }
139 }
140 }
140 }
141
141
142 pre {
142 pre {
143 margin: 0;
143 margin: 0;
144 padding: 0;
144 padding: 0;
145 border: 0;
145 border: 0;
146 outline: 0;
146 outline: 0;
147 font-size: @basefontsize*.95;
147 font-size: @basefontsize*.95;
148 line-height: 1.4em;
148 line-height: 1.4em;
149 font-family: @text-code;
149 font-family: @text-code;
150 color: @grey3;
150 color: @grey3;
151 }
151 }
152
152
153 // Emphasis & misc
153 // Emphasis & misc
154 // -------------------------
154 // -------------------------
155
155
156 small,
156 small,
157 .small {
157 .small {
158 font-size: 75%;
158 font-size: 75%;
159 font-weight: normal;
159 font-weight: normal;
160 line-height: 1em;
160 line-height: 1em;
161 }
161 }
162
162
163 mark,
163 mark,
164 .mark {
164 .mark {
165 background-color: @rclightblue;
165 background-color: @rclightblue;
166 padding: .2em;
166 padding: .2em;
167 }
167 }
168
168
169 // Alignment
169 // Alignment
170 .text-left { text-align: left; }
170 .text-left { text-align: left; }
171 .text-right { text-align: right; }
171 .text-right { text-align: right; }
172 .text-center { text-align: center; }
172 .text-center { text-align: center; }
173 .text-justify { text-align: justify; }
173 .text-justify { text-align: justify; }
174 .text-nowrap { white-space: nowrap; }
174 .text-nowrap { white-space: nowrap; }
175
175
176 // Transformation
176 // Transformation
177 .text-lowercase { text-transform: lowercase; }
177 .text-lowercase { text-transform: lowercase; }
178 .text-uppercase { text-transform: uppercase; }
178 .text-uppercase { text-transform: uppercase; }
179 .text-capitalize { text-transform: capitalize; }
179 .text-capitalize { text-transform: capitalize; }
180
180
181 // Contextual colors
181 // Contextual colors
182 .text-muted {
182 .text-muted {
183 color: @grey4;
183 color: @grey4;
184 }
184 }
185 .text-primary {
185 .text-primary {
186 color: @rcblue;
186 color: @rcblue;
187 }
187 }
188 .text-success {
188 .text-success {
189 color: @alert1;
189 color: @alert1;
190 }
190 }
191 .text-info {
191 .text-info {
192 color: @alert4;
192 color: @alert4;
193 }
193 }
194 .text-warning {
194 .text-warning {
195 color: @alert3;
195 color: @alert3;
196 }
196 }
197 .text-danger {
197 .text-danger {
198 color: @alert2;
198 color: @alert2;
199 }
199 }
200
200
201 // Contextual backgrounds
201 // Contextual backgrounds
202 .bg-primary {
202 .bg-primary {
203 background-color: white;
203 background-color: white;
204 }
204 }
205 .bg-success {
205 .bg-success {
206 background-color: @alert1;
206 background-color: @alert1;
207 }
207 }
208 .bg-info {
208 .bg-info {
209 background-color: @alert4;
209 background-color: @alert4;
210 }
210 }
211 .bg-warning {
211 .bg-warning {
212 background-color: @alert3;
212 background-color: @alert3;
213 }
213 }
214 .bg-danger {
214 .bg-danger {
215 background-color: @alert2;
215 background-color: @alert2;
216 }
216 }
217
217
218
218
219 // Page header
219 // Page header
220 // -------------------------
220 // -------------------------
221
221
222 .page-header {
222 .page-header {
223 margin: @pagepadding 0 @textmargin;
223 margin: @pagepadding 0 @textmargin;
224 border-bottom: @border-thickness solid @grey5;
224 border-bottom: @border-thickness solid @grey5;
225 }
225 }
226
226
227 .title {
227 .title {
228 clear: both;
228 clear: both;
229 float: left;
229 float: left;
230 width: 100%;
230 width: 100%;
231 margin: @pagepadding/2 0 @pagepadding;
231 margin: @pagepadding/2 0 @pagepadding;
232
232
233 .breadcrumbs{
233 .breadcrumbs {
234 float: left;
234 float: left;
235 clear: both;
235 clear: both;
236 width: 700px;
236 width: 700px;
237 margin: 0;
237 margin: 0;
238
238
239 .q_filter_box {
239 .q_filter_box {
240 margin-right: @padding;
240 margin-right: @padding;
241 }
241 }
242 }
242 }
243
243
244 h1 a {
244 h1 a {
245 color: @rcblue;
245 color: @rcblue;
246 }
246 }
247
247
248 input{
248 input{
249 margin-right: @padding;
249 margin-right: @padding;
250 }
250 }
251
251
252 h5, .h5 {
252 h5, .h5 {
253 color: @grey1;
253 color: @grey1;
254 margin-bottom: @space;
254 margin-bottom: @space;
255
255
256 span {
256 span {
257 display: inline-block;
257 display: inline-block;
258 }
258 }
259 }
259 }
260
260
261 p {
261 p {
262 margin-bottom: 0;
262 margin-bottom: 0;
263 }
263 }
264
264
265 .links {
265 .links {
266 float: right;
266 float: right;
267 display: inline;
267 display: inline;
268 margin: 0;
268 margin: 0;
269 padding-left: 0;
269 padding-left: 0;
270 list-style: none;
270 list-style: none;
271 text-align: right;
271 text-align: right;
272
272
273 li:before { content: none; }
273 li:before { content: none; }
274 li { float: right; }
274 li { float: right; }
275 a {
275 a {
276 display: inline-block;
276 display: inline-block;
277 margin-left: @textmargin/2;
277 margin-left: @textmargin/2;
278 }
278 }
279 }
279 }
280
280
281 .title-content {
281 .title-content {
282 float: left;
282 float: left;
283 margin: 0;
283 margin: 0;
284 padding: 0;
284 padding: 0;
285
285
286 & + .breadcrumbs {
286 & + .breadcrumbs {
287 margin-top: @padding;
287 margin-top: @padding;
288 }
288 }
289
289
290 & + .links {
290 & + .links {
291 margin-top: -@button-padding;
291 margin-top: -@button-padding;
292
292
293 & + .breadcrumbs {
293 & + .breadcrumbs {
294 margin-top: @padding;
294 margin-top: @padding;
295 }
295 }
296 }
296 }
297 }
297 }
298
298
299 .title-main {
299 .title-main {
300 font-size: @repo-title-fontsize;
300 font-size: @repo-title-fontsize;
301 }
301 }
302
302
303 .title-description {
303 .title-description {
304 margin-top: .5em;
304 margin-top: .5em;
305 }
305 }
306
306
307 .q_filter_box {
307 .q_filter_box {
308 width: 200px;
308 width: 200px;
309 }
309 }
310
310
311 }
311 }
312
312
313 #readme .title {
313 #readme .title {
314 text-transform: none;
314 text-transform: none;
315 }
315 }
316
316
317 // Lists
317 // Lists
318 // -------------------------
318 // -------------------------
319
319
320 // Unordered and Ordered lists
320 // Unordered and Ordered lists
321 ul,
321 ul,
322 ol {
322 ol {
323 margin-top: 0;
323 margin-top: 0;
324 margin-bottom: @textmargin;
324 margin-bottom: @textmargin;
325 ul,
325 ul,
326 ol {
326 ol {
327 margin-bottom: 0;
327 margin-bottom: 0;
328 }
328 }
329 }
329 }
330
330
331 li {
331 li {
332 line-height: 2em;
332 line-height: 2em;
333 }
333 }
334
334
335 ul li {
335 ul li {
336 position: relative;
336 position: relative;
337 display: block;
337 display: block;
338 list-style-type: none;
338 list-style-type: none;
339
339
340 &:before {
340 &:before {
341 content: "\2014\00A0";
341 content: "\2014\00A0";
342 position: absolute;
342 position: absolute;
343 top: 0;
343 top: 0;
344 left: -1.25em;
344 left: -1.25em;
345 }
345 }
346
346
347 p:first-child {
347 p:first-child {
348 display:inline;
348 display:inline;
349 }
349 }
350 }
350 }
351
351
352 // List options
352 // List options
353
353
354 // Unstyled keeps list items block level, just removes default browser padding and list-style
354 // Unstyled keeps list items block level, just removes default browser padding and list-style
355 .list-unstyled {
355 .list-unstyled {
356 padding-left: 0;
356 padding-left: 0;
357 list-style: none;
357 list-style: none;
358 li:before { content: none; }
358 li:before { content: none; }
359 }
359 }
360
360
361 // Inline turns list items into inline-block
361 // Inline turns list items into inline-block
362 .list-inline {
362 .list-inline {
363 .list-unstyled();
363 .list-unstyled();
364 margin-left: -5px;
364 margin-left: -5px;
365
365
366 > li {
366 > li {
367 display: inline-block;
367 display: inline-block;
368 padding-left: 5px;
368 padding-left: 5px;
369 padding-right: 5px;
369 padding-right: 5px;
370 }
370 }
371 }
371 }
372
372
373 // Description Lists
373 // Description Lists
374
374
375 dl {
375 dl {
376 margin-top: 0; // Remove browser default
376 margin-top: 0; // Remove browser default
377 margin-bottom: @textmargin;
377 margin-bottom: @textmargin;
378 }
378 }
379
379
380 dt,
380 dt,
381 dd {
381 dd {
382 line-height: 1.4em;
382 line-height: 1.4em;
383 }
383 }
384
384
385 dt {
385 dt {
386 margin: @textmargin 0 0 0;
386 margin: @textmargin 0 0 0;
387 font-family: @text-bold;
387 font-family: @text-bold;
388 }
388 }
389
389
390 dd {
390 dd {
391 margin-left: 0; // Undo browser default
391 margin-left: 0; // Undo browser default
392 }
392 }
393
393
394 // Horizontal description lists
394 // Horizontal description lists
395 // Defaults to being stacked without any of the below styles applied, until the
395 // Defaults to being stacked without any of the below styles applied, until the
396 // grid breakpoint is reached (default of ~768px).
396 // grid breakpoint is reached (default of ~768px).
397 // These are used in forms as well; see style guide.
397 // These are used in forms as well; see style guide.
398 // TODO: lisa: These should really not be used in forms.
398 // TODO: lisa: These should really not be used in forms.
399
399
400 .dl-horizontal {
400 .dl-horizontal {
401
401
402 overflow: hidden;
402 overflow: hidden;
403 margin-bottom: @space;
403 margin-bottom: @space;
404
404
405 dt, dd {
405 dt, dd {
406 float: left;
406 float: left;
407 margin: 5px 0 5px 0;
407 margin: 5px 0 5px 0;
408 }
408 }
409
409
410 dt {
410 dt {
411 clear: left;
411 clear: left;
412 width: @label-width - @form-vertical-margin;
412 width: @label-width - @form-vertical-margin;
413 }
413 }
414
414
415 dd {
415 dd {
416 &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present
416 &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present
417 margin-left: @form-vertical-margin;
417 margin-left: @form-vertical-margin;
418 max-width: @form-max-width - (@label-width - @form-vertical-margin) - @form-vertical-margin;
418 max-width: @form-max-width - (@label-width - @form-vertical-margin) - @form-vertical-margin;
419 }
419 }
420
420
421 pre {
421 pre {
422 margin: 0;
422 margin: 0;
423 }
423 }
424
424
425 &.settings {
425 &.settings {
426 dt {
426 dt {
427 text-align: left;
427 text-align: left;
428 }
428 }
429 }
429 }
430
430
431 @media (min-width: 768px) {
431 @media (min-width: 768px) {
432 dt {
432 dt {
433 float: left;
433 float: left;
434 width: 180px;
434 width: 180px;
435 clear: left;
435 clear: left;
436 text-align: right;
436 text-align: right;
437 }
437 }
438 dd {
438 dd {
439 margin-left: 20px;
439 margin-left: 20px;
440 }
440 }
441 }
441 }
442 }
442 }
443
443
444
444
445 // Misc
445 // Misc
446 // -------------------------
446 // -------------------------
447
447
448 // Abbreviations and acronyms
448 // Abbreviations and acronyms
449 abbr[title],
449 abbr[title],
450 abbr[data-original-title] {
450 abbr[data-original-title] {
451 cursor: help;
451 cursor: help;
452 border-bottom: @border-thickness dotted @grey4;
452 border-bottom: @border-thickness dotted @grey4;
453 }
453 }
454 .initialism {
454 .initialism {
455 font-size: 90%;
455 font-size: 90%;
456 text-transform: uppercase;
456 text-transform: uppercase;
457 }
457 }
458
458
459 // Blockquotes
459 // Blockquotes
460 blockquote {
460 blockquote {
461 padding: 1em 2em;
461 padding: 1em 2em;
462 margin: 0 0 2em;
462 margin: 0 0 2em;
463 font-size: @basefontsize;
463 font-size: @basefontsize;
464 border-left: 2px solid @grey6;
464 border-left: 2px solid @grey6;
465
465
466 p,
466 p,
467 ul,
467 ul,
468 ol {
468 ol {
469 &:last-child {
469 &:last-child {
470 margin-bottom: 0;
470 margin-bottom: 0;
471 }
471 }
472 }
472 }
473
473
474 footer,
474 footer,
475 small,
475 small,
476 .small {
476 .small {
477 display: block;
477 display: block;
478 font-size: 80%;
478 font-size: 80%;
479
479
480 &:before {
480 &:before {
481 content: '\2014 \00A0'; // em dash, nbsp
481 content: '\2014 \00A0'; // em dash, nbsp
482 }
482 }
483 }
483 }
484 }
484 }
485
485
486 // Opposite alignment of blockquote
486 // Opposite alignment of blockquote
487 //
487 //
488 .blockquote-reverse,
488 .blockquote-reverse,
489 blockquote.pull-right {
489 blockquote.pull-right {
490 padding-right: 15px;
490 padding-right: 15px;
491 padding-left: 0;
491 padding-left: 0;
492 border-right: 5px solid @grey6;
492 border-right: 5px solid @grey6;
493 border-left: 0;
493 border-left: 0;
494 text-align: right;
494 text-align: right;
495
495
496 // Account for citation
496 // Account for citation
497 footer,
497 footer,
498 small,
498 small,
499 .small {
499 .small {
500 &:before { content: ''; }
500 &:before { content: ''; }
501 &:after {
501 &:after {
502 content: '\00A0 \2014'; // nbsp, em dash
502 content: '\00A0 \2014'; // nbsp, em dash
503 }
503 }
504 }
504 }
505 }
505 }
506
506
507 // Addresses
507 // Addresses
508 address {
508 address {
509 margin-bottom: 2em;
509 margin-bottom: 2em;
510 font-style: normal;
510 font-style: normal;
511 line-height: 1.8em;
511 line-height: 1.8em;
512 }
512 }
513
513
514 .error-message {
514 .error-message {
515 display: block;
515 display: block;
516 margin: @padding/3 0;
516 margin: @padding/3 0;
517 color: @alert2;
517 color: @alert2;
518 }
518 }
519
519
520 .issue-tracker-link {
520 .issue-tracker-link {
521 color: @rcblue;
521 color: @rcblue;
522 }
522 }
523
523
524 .info_text{
524 .info_text{
525 font-size: @basefontsize;
525 font-size: @basefontsize;
526 color: @grey4;
526 color: @grey4;
527 font-family: @text-regular;
527 font-family: @text-regular;
528 }
528 }
529
529
530 // help block text
530 // help block text
531 .help-block {
531 .help-block {
532 display: block;
532 display: block;
533 margin: 0 0 @padding;
533 margin: 0 0 @padding;
534 color: @grey4;
534 color: @grey4;
535 font-family: @text-light;
535 font-family: @text-light;
536 &.pre-formatting {
536 &.pre-formatting {
537 white-space: pre;
537 white-space: pre;
538 }
538 }
539 }
539 }
540
540
541 .error-message {
541 .error-message {
542 display: block;
542 display: block;
543 margin: @padding/3 0;
543 margin: @padding/3 0;
544 color: @alert2;
544 color: @alert2;
545 }
545 }
@@ -1,138 +1,138 b''
1 // variables for use in all RhodeCode products
1 // variables for use in all RhodeCode products
2
2
3 // FONTS
3 // FONTS
4 //Primary Colors (brand)
4 //Primary Colors (brand)
5 @rcblue: #427cc9; //RhodeCode blue
5 @rcblue: #427cc9; //RhodeCode blue
6 @rcdarkblue: #305b91; //RhodeCode dark blue
6 @rcdarkblue: #305b91; //RhodeCode dark blue
7 @rclightblue: lighten(@rcblue, 30%);
7 @rclightblue: lighten(@rcblue, 30%);
8 @rchighlightblue: lighten(@rcblue, 35%);
8 @rchighlightblue: lighten(@rcblue, 35%);
9
9
10 // Secondary Colors (greyscale)
10 // Secondary Colors (greyscale)
11 @grey1: #202020; //midnight
11 @grey1: #202020; //midnight
12 @grey2: #323232; //charcoal
12 @grey2: #323232; //charcoal
13 @grey3: #666666; //tungsten
13 @grey3: #666666; //tungsten
14 @grey4: #979797; //light grey
14 @grey4: #979797; //light grey
15 @grey5: #dbd9da; //greyish
15 @grey5: #dbd9da; //greyish
16 @grey6: #eeeeee; //silver
16 @grey6: #eeeeee; //silver
17 @grey7: #f9f9f9; //light silver
17 @grey7: #f9f9f9; //light silver
18
18
19 // special for navigation
19 // special for navigation
20 @nav-grey: #CDCCCD;
20 @nav-grey: #CDCCCD;
21
21
22 @grey5-alpha: rgba(219, 217, 218, 0.3);
22 @grey5-alpha: rgba(219, 217, 218, 0.3);
23
23
24 // Tertiary Colors
24 // Tertiary Colors
25 @color1: #879938; //olive green
25 @color1: #879938; //olive green
26 @color2: #fcc93a; //bright yellow
26 @color2: #fcc93a; //bright yellow
27 @color3: #ff9e07; //orange-yellow
27 @color3: #ff9e07; //orange-yellow
28 @color4: #fc663a; //bright orange
28 @color4: #fc663a; //bright orange
29 @color5: #d63d44; //signal red
29 @color5: #d63d44; //signal red
30 @color6: #99287c; //violet
30 @color6: #99287c; //violet
31 @color7: #682668; //dark purple
31 @color7: #682668; //dark purple
32 @color8: #194f8e; //dark blue
32 @color8: #194f8e; //dark blue
33
33
34 // Alert Colors (bright)
34 // Alert Colors (bright)
35 @alert1: #0ac878; //bright green
35 @alert1: #0ac878; //bright green
36 @alert2: #e85e4d; //soft red
36 @alert2: #e85e4d; //soft red
37 @alert3: #ffc854; //corn yellow
37 @alert3: #ffc854; //corn yellow
38 @alert4: #84a5d2; //light blue
38 @alert4: #84a5d2; //light blue
39
39
40 // Alert Inner Colors
40 // Alert Inner Colors
41 @alert1-inner: #daf7eb; //bright green
41 @alert1-inner: #daf7eb; //bright green
42 @alert2-inner: #fbdfdb; //soft red
42 @alert2-inner: #fbdfdb; //soft red
43 @alert3-inner: #fff4dd; //corn yellow
43 @alert3-inner: #fff4dd; //corn yellow
44 @alert4-inner: #e6edf6; //light blue
44 @alert4-inner: #e6edf6; //light blue
45
45
46 // Highlight color for lines and colors
46 // Highlight color for lines and colors
47 @comment-highlight-color: #ffd887;
47 @comment-highlight-color: #ffd887;
48
48
49 // FONTS
49 // FONTS
50 @basefontsize: 13px;
50 @basefontsize: 13px;
51 @navigation-fontsize: 14px;
51 @navigation-fontsize: 14px;
52 @journal-fontsize: @basefontsize+7px;
52 @journal-fontsize: @basefontsize+7px;
53 @text-color: @grey2;
53 @text-color: @grey2;
54 @repo-title-fontsize: 18px;
54 @repo-title-fontsize: 18px;
55
55
56 @text-regular: "proximanovaregular","Proxima Nova Regular", "Proxima Nova", sans-serif;
56 @text-regular: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
57 @text-italic: "proximanovaitalic","Proxima Nova Italic", "Proxima Nova", sans-serif;
57 @text-italic: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
58 @text-bold: "proximanovabold","Proxima Nova Bold", "Proxima Nova", sans-serif;
58 @text-bold: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
59 @text-semibold: "proximanovasemibold","Proxima Nova Semibold", "Proxima Nova", sans-serif;
59 @text-semibold: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
60 @text-bold-italic: "proximanovabolditalic","Proxima Nova Bold Italic", "Proxima Nova", sans-serif;
60 @text-bold-italic: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
61 @text-code: "Lucida Console", Menlo, Monaco, monospace;
61 @text-code: 'Menlo', 'Liberation Mono', 'Consolas', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Courier New', 'andale mono', 'lucida console', monospace;
62 @text-light: @text-regular;
62 @text-light: @text-regular;
63 @text-light-italic: @text-italic;
63 @text-light-italic: @text-italic;
64 // Used for .close buttons
64 // Used for .close buttons
65 @text-bootstrap: "Helvetica Neue", Helvetica, Arial, sans-serif;
65 @text-bootstrap: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
66
66
67 @panel-title: @basefontsize;
67 @panel-title: @basefontsize;
68 @panel-footer: @basefontsize;
68 @panel-footer: @basefontsize;
69
69
70 // BORDERS
70 // BORDERS
71 @border-thickness: 1px;
71 @border-thickness: 1px;
72 @border-thickness-buttons: 1px;
72 @border-thickness-buttons: 1px;
73 @border-thickness-tags: 1px;
73 @border-thickness-tags: 1px;
74 @border-radius: 2px;
74 @border-radius: 2px;
75 @border-default-color: @grey5;
75 @border-default-color: @grey5;
76 @border-highlight-color: @grey4;
76 @border-highlight-color: @grey4;
77
77
78 // SPACING
78 // SPACING
79 @contentpadding: 15px; //padding on left and right of pages
79 @contentpadding: 15px; //padding on left and right of pages
80 @pagepadding: 40px; //padding on top and bottom of pages
80 @pagepadding: 40px; //padding on top and bottom of pages
81 @menupadding: 12px; //padding for sidebar and content
81 @menupadding: 12px; //padding for sidebar and content
82 @sidebarpadding: 15px; //spacing between sections
82 @sidebarpadding: 15px; //spacing between sections
83 @space: 40px; //spacing between sections
83 @space: 40px; //spacing between sections
84 @padding: 15px; //padding inside modules
84 @padding: 15px; //padding inside modules
85 @textmargin: 20px; //spacing below headers
85 @textmargin: 20px; //spacing below headers
86 @header-padding: 20px;
86 @header-padding: 20px;
87 @panel-padding: @padding;
87 @panel-padding: @padding;
88 @gravatar-size: 16px; // height/width of gravatar w/o border
88 @gravatar-size: 16px; // height/width of gravatar w/o border
89
89
90 // ADMIN
90 // ADMIN
91 @form-max-width: 750px;
91 @form-max-width: 750px;
92
92
93 // FORMS (new)
93 // FORMS (new)
94 @border-thickness-inputs: 1px;
94 @border-thickness-inputs: 1px;
95 @input-padding: @button-padding; //needs to match button padding
95 @input-padding: @button-padding; //needs to match button padding
96 // TODO: johbo: Needed for working computation of paddings around labels etc.
96 // TODO: johbo: Needed for working computation of paddings around labels etc.
97 // Expected to be replaced once we are done with the form refactoring.
97 // Expected to be replaced once we are done with the form refactoring.
98 @input-padding-px: 12px;
98 @input-padding-px: 12px;
99 @legend-width: 220px;
99 @legend-width: 220px;
100 @form-vertical-margin: 20px;
100 @form-vertical-margin: 20px;
101 @form-check-width: 20px;
101 @form-check-width: 20px;
102 @form-radio-width: 10px;
102 @form-radio-width: 10px;
103 @form-textcolor: @grey3;
103 @form-textcolor: @grey3;
104
104
105 // FORMS
105 // FORMS
106 @label-width: 220px;
106 @label-width: 220px;
107 //TODO: lisa: Eventually we don't need both of these; remove
107 //TODO: lisa: Eventually we don't need both of these; remove
108 // label-width when legend-width is no longer used
108 // label-width when legend-width is no longer used
109
109
110 @input-border-thickness: @border-thickness;
110 @input-border-thickness: @border-thickness;
111 @medium-inline-input-width: 115px;
111 @medium-inline-input-width: 115px;
112 @input-description-minwidth: 300px;
112 @input-description-minwidth: 300px;
113 @label2-width: 200px;
113 @label2-width: 200px;
114 @checkboxes-width: 420px;
114 @checkboxes-width: 420px;
115 @label-summary-minwidth: 80px;
115 @label-summary-minwidth: 80px;
116 @search-form-width: 400px;
116 @search-form-width: 400px;
117 @fields-input-m: 400px;
117 @fields-input-m: 400px;
118 @fields-input-l: 800px;
118 @fields-input-l: 800px;
119
119
120 // BUTTONS
120 // BUTTONS
121 @button-padding: .9em;
121 @button-padding: .9em;
122
122
123 // DEFAULT WIDTHS
123 // DEFAULT WIDTHS
124 @wrapper-maxwidth: 1200px;
124 @wrapper-maxwidth: 1200px;
125 @sidebar-width: 145px;
125 @sidebar-width: 145px;
126 @sidebar-all-width: @sidebar-width + 2 * @sidebarpadding;
126 @sidebar-all-width: @sidebar-width + 2 * @sidebarpadding;
127 @sidebar-small-width: 100px;
127 @sidebar-small-width: 100px;
128 @sidebar-small-all-width: @sidebar-small-width + 2 * @sidebarpadding;
128 @sidebar-small-all-width: @sidebar-small-width + 2 * @sidebarpadding;
129 @texteditor-width: 660px;
129 @texteditor-width: 660px;
130 @maincontent-maxwidth: 940px;
130 @maincontent-maxwidth: 940px;
131 @pullrequest-width: 1025px;
131 @pullrequest-width: 1025px;
132 @summary-menu-stats-width: 200px;
132 @summary-menu-stats-width: 200px;
133
133
134 // SCREEN WIDTHS
134 // SCREEN WIDTHS
135 @screen-sm-min: 320px;
135 @screen-sm-min: 320px;
136
136
137 // For Bootstrap
137 // For Bootstrap
138 @panel-border-radius: @border-radius;
138 @panel-border-radius: @border-radius;
@@ -1,152 +1,152 b''
1 ## small box that displays changed/added/removed details fetched by AJAX
1 ## small box that displays changed/added/removed details fetched by AJAX
2 <%namespace name="base" file="/base/base.mako"/>
2 <%namespace name="base" file="/base/base.mako"/>
3
3
4
4
5 % if c.prev_page:
5 % if c.prev_page:
6 <tr>
6 <tr>
7 <td colspan="9" class="load-more-commits">
7 <td colspan="9" class="load-more-commits">
8 <a class="prev-commits" href="#loadPrevCommits" onclick="commitsController.loadPrev(this, ${c.prev_page}, '${c.branch_name}', '${c.commit_id}', '${c.f_path}');return false">
8 <a class="prev-commits" href="#loadPrevCommits" onclick="commitsController.loadPrev(this, ${c.prev_page}, '${c.branch_name}', '${c.commit_id}', '${c.f_path}');return false">
9 ${_('load previous')}
9 ${_('load previous')}
10 </a>
10 </a>
11 </td>
11 </td>
12 </tr>
12 </tr>
13 % endif
13 % endif
14
14
15 ## to speed up lookups cache some functions before the loop
15 ## to speed up lookups cache some functions before the loop
16 <%
16 <%
17 active_patterns = h.get_active_pattern_entries(c.repo_name)
17 active_patterns = h.get_active_pattern_entries(c.repo_name)
18 urlify_commit_message = h.partial(h.urlify_commit_message, active_pattern_entries=active_patterns)
18 urlify_commit_message = h.partial(h.urlify_commit_message, active_pattern_entries=active_patterns)
19 %>
19 %>
20
20
21 % for cnt,commit in enumerate(c.pagination):
21 % for cnt,commit in enumerate(c.pagination):
22 <tr id="sha_${commit.raw_id}" class="changelogRow container ${'tablerow%s' % (cnt%2)}">
22 <tr id="sha_${commit.raw_id}" class="changelogRow container ${'tablerow%s' % (cnt%2)}">
23
23
24 <td class="td-checkbox">
24 <td class="td-checkbox">
25 ${h.checkbox(commit.raw_id,class_="commit-range")}
25 ${h.checkbox(commit.raw_id,class_="commit-range")}
26 </td>
26 </td>
27 <td class="td-status">
27 <td class="td-status">
28
28
29 %if c.statuses.get(commit.raw_id):
29 %if c.statuses.get(commit.raw_id):
30 <div class="changeset-status-ico">
30 <div class="changeset-status-ico">
31 %if c.statuses.get(commit.raw_id)[2]:
31 %if c.statuses.get(commit.raw_id)[2]:
32 <a class="tooltip" title="${_('Commit status: %s\nClick to open associated pull request #%s') % (h.commit_status_lbl(c.statuses.get(commit.raw_id)[0]), c.statuses.get(commit.raw_id)[2])}" href="${h.route_path('pullrequest_show',repo_name=c.statuses.get(commit.raw_id)[3],pull_request_id=c.statuses.get(commit.raw_id)[2])}">
32 <a class="tooltip" title="${_('Commit status: %s\nClick to open associated pull request #%s') % (h.commit_status_lbl(c.statuses.get(commit.raw_id)[0]), c.statuses.get(commit.raw_id)[2])}" href="${h.route_path('pullrequest_show',repo_name=c.statuses.get(commit.raw_id)[3],pull_request_id=c.statuses.get(commit.raw_id)[2])}">
33 <div class="${'flag_status {}'.format(c.statuses.get(commit.raw_id)[0])}"></div>
33 <div class="${'flag_status {}'.format(c.statuses.get(commit.raw_id)[0])}"></div>
34 </a>
34 </a>
35 %else:
35 %else:
36 <a class="tooltip" title="${_('Commit status: {}').format(h.commit_status_lbl(c.statuses.get(commit.raw_id)[0]))}" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id,_anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
36 <a class="tooltip" title="${_('Commit status: {}').format(h.commit_status_lbl(c.statuses.get(commit.raw_id)[0]))}" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id,_anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
37 <div class="${'flag_status {}'.format(c.statuses.get(commit.raw_id)[0])}"></div>
37 <div class="${'flag_status {}'.format(c.statuses.get(commit.raw_id)[0])}"></div>
38 </a>
38 </a>
39 %endif
39 %endif
40 </div>
40 </div>
41 %else:
41 %else:
42 <div class="tooltip flag_status not_reviewed" title="${_('Commit status: Not Reviewed')}"></div>
42 <div class="tooltip flag_status not_reviewed" title="${_('Commit status: Not Reviewed')}"></div>
43 %endif
43 %endif
44 </td>
44 </td>
45 <td class="td-comments comments-col">
45 <td class="td-comments comments-col">
46 %if c.comments.get(commit.raw_id):
46 %if c.comments.get(commit.raw_id):
47 <a title="${_('Commit has comments')}" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id,_anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
47 <a title="${_('Commit has comments')}" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id,_anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
48 <i class="icon-comment"></i> ${len(c.comments[commit.raw_id])}
48 <i class="icon-comment"></i> ${len(c.comments[commit.raw_id])}
49 </a>
49 </a>
50 %endif
50 %endif
51 </td>
51 </td>
52 <td class="td-hash">
52 <td class="td-hash">
53 <code>
53 <code>
54
54
55 <a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id)}">
55 <a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id)}">
56 <span class="${'commit_hash obsolete' if getattr(commit, 'obsolete', None) else 'commit_hash'}">${h.show_id(commit)}</span>
56 <span class="${'commit_hash obsolete' if getattr(commit, 'obsolete', None) else 'commit_hash'}">${h.show_id(commit)}</span>
57 </a>
57 </a>
58 <i class="tooltip icon-clipboard clipboard-action" data-clipboard-text="${commit.raw_id}" title="${_('Copy the full commit id')}"></i>
58 <i class="tooltip icon-clipboard clipboard-action" data-clipboard-text="${commit.raw_id}" title="${_('Copy the full commit id')}"></i>
59 </code>
59 </code>
60 </td>
60 </td>
61 <td class="td-tags tags-col">
61 <td class="td-tags tags-col">
62 ## phase
62 ## phase
63 % if hasattr(commit, 'phase'):
63 % if hasattr(commit, 'phase'):
64 % if commit.phase != 'public':
64 % if commit.phase != 'public':
65 <span class="tag phase-${commit.phase} tooltip" title="${_('Commit phase')}">${commit.phase}</span>
65 <span class="tag phase-${commit.phase} tooltip" title="${_('Commit phase')}">${commit.phase}</span>
66 % endif
66 % endif
67 % endif
67 % endif
68
68
69 ## obsolete commits
69 ## obsolete commits
70 % if hasattr(commit, 'obsolete'):
70 % if hasattr(commit, 'obsolete'):
71 % if commit.obsolete:
71 % if commit.obsolete:
72 <span class="tag obsolete-${commit.obsolete} tooltip" title="${_('Evolve State')}">${_('obsolete')}</span>
72 <span class="tag obsolete-${commit.obsolete} tooltip" title="${_('Evolve State')}">${_('obsolete')}</span>
73 % endif
73 % endif
74 % endif
74 % endif
75
75
76 ## hidden commits
76 ## hidden commits
77 % if hasattr(commit, 'hidden'):
77 % if hasattr(commit, 'hidden'):
78 % if commit.hidden:
78 % if commit.hidden:
79 <span class="tag obsolete-${commit.hidden} tooltip" title="${_('Evolve State')}">${_('hidden')}</span>
79 <span class="tag obsolete-${commit.hidden} tooltip" title="${_('Evolve State')}">${_('hidden')}</span>
80 % endif
80 % endif
81 % endif
81 % endif
82 </td>
82 </td>
83 <td class="td-message expand_commit" data-commit-id="${commit.raw_id}" title="${_('Expand commit message')}" onclick="commitsController.expandCommit(this); return false">
83 <td class="td-message expand_commit" data-commit-id="${commit.raw_id}" title="${_('Expand commit message')}" onclick="commitsController.expandCommit(this); return false">
84 <div class="show_more_col">
84 <div class="show_more_col">
85 <i class="show_more"></i>&nbsp;
85 <i class="icon-more-linked"></i>&nbsp;
86 </div>
86 </div>
87 </td>
87 </td>
88 <td class="td-description mid">
88 <td class="td-description mid">
89 <div class="log-container truncate-wrap">
89 <div class="log-container truncate-wrap">
90 <div class="message truncate" id="c-${commit.raw_id}">${urlify_commit_message(commit.message, c.repo_name)}</div>
90 <div class="message truncate" id="c-${commit.raw_id}">${urlify_commit_message(commit.message, c.repo_name)}</div>
91 </div>
91 </div>
92 </td>
92 </td>
93
93
94 <td class="td-time">
94 <td class="td-time">
95 ${h.age_component(commit.date)}
95 ${h.age_component(commit.date)}
96 </td>
96 </td>
97 <td class="td-user">
97 <td class="td-user">
98 ${base.gravatar_with_user(commit.author)}
98 ${base.gravatar_with_user(commit.author)}
99 </td>
99 </td>
100
100
101 <td class="td-tags tags-col">
101 <td class="td-tags tags-col">
102 <div id="t-${commit.raw_id}">
102 <div id="t-${commit.raw_id}">
103
103
104 ## merge
104 ## merge
105 %if commit.merge:
105 %if commit.merge:
106 <span class="tag mergetag">
106 <span class="tag mergetag">
107 <i class="icon-merge"></i>${_('merge')}
107 <i class="icon-merge"></i>${_('merge')}
108 </span>
108 </span>
109 %endif
109 %endif
110
110
111 ## branch
111 ## branch
112 %if commit.branch:
112 %if commit.branch:
113 <span class="tag branchtag" title="${h.tooltip(_('Branch %s') % commit.branch)}">
113 <span class="tag branchtag" title="${h.tooltip(_('Branch %s') % commit.branch)}">
114 <a href="${h.route_path('repo_changelog',repo_name=c.repo_name,_query=dict(branch=commit.branch))}"><i class="icon-code-fork"></i>${h.shorter(commit.branch)}</a>
114 <a href="${h.route_path('repo_changelog',repo_name=c.repo_name,_query=dict(branch=commit.branch))}"><i class="icon-code-fork"></i>${h.shorter(commit.branch)}</a>
115 </span>
115 </span>
116 %endif
116 %endif
117
117
118 ## bookmarks
118 ## bookmarks
119 %if h.is_hg(c.rhodecode_repo):
119 %if h.is_hg(c.rhodecode_repo):
120 %for book in commit.bookmarks:
120 %for book in commit.bookmarks:
121 <span class="tag booktag" title="${h.tooltip(_('Bookmark %s') % book)}">
121 <span class="tag booktag" title="${h.tooltip(_('Bookmark %s') % book)}">
122 <a href="${h.route_path('repo_files:default_path',repo_name=c.repo_name,commit_id=commit.raw_id, _query=dict(at=book))}"><i class="icon-bookmark"></i>${h.shorter(book)}</a>
122 <a href="${h.route_path('repo_files:default_path',repo_name=c.repo_name,commit_id=commit.raw_id, _query=dict(at=book))}"><i class="icon-bookmark"></i>${h.shorter(book)}</a>
123 </span>
123 </span>
124 %endfor
124 %endfor
125 %endif
125 %endif
126
126
127 ## tags
127 ## tags
128 %for tag in commit.tags:
128 %for tag in commit.tags:
129 <span class="tag tagtag" title="${h.tooltip(_('Tag %s') % tag)}">
129 <span class="tag tagtag" title="${h.tooltip(_('Tag %s') % tag)}">
130 <a href="${h.route_path('repo_files:default_path',repo_name=c.repo_name,commit_id=commit.raw_id, _query=dict(at=tag))}"><i class="icon-tag"></i>${h.shorter(tag)}</a>
130 <a href="${h.route_path('repo_files:default_path',repo_name=c.repo_name,commit_id=commit.raw_id, _query=dict(at=tag))}"><i class="icon-tag"></i>${h.shorter(tag)}</a>
131 </span>
131 </span>
132 %endfor
132 %endfor
133
133
134 </div>
134 </div>
135 </td>
135 </td>
136 </tr>
136 </tr>
137 % endfor
137 % endfor
138
138
139 % if c.next_page:
139 % if c.next_page:
140 <tr>
140 <tr>
141 <td colspan="10" class="load-more-commits">
141 <td colspan="10" class="load-more-commits">
142 <a class="next-commits" href="#loadNextCommits" onclick="commitsController.loadNext(this, ${c.next_page}, '${c.branch_name}', '${c.commit_id}', '${c.f_path}');return false">
142 <a class="next-commits" href="#loadNextCommits" onclick="commitsController.loadNext(this, ${c.next_page}, '${c.branch_name}', '${c.commit_id}', '${c.f_path}');return false">
143 ${_('load next')}
143 ${_('load next')}
144 </a>
144 </a>
145 </td>
145 </td>
146 </tr>
146 </tr>
147 % endif
147 % endif
148 <tr class="chunk-graph-data" style="display:none"
148 <tr class="chunk-graph-data" style="display:none"
149 data-graph='${c.graph_data|n}'
149 data-graph='${c.graph_data|n}'
150 data-node='${c.prev_page}:${c.next_page}'
150 data-node='${c.prev_page}:${c.next_page}'
151 data-commits='${c.graph_commits|n}'>
151 data-commits='${c.graph_commits|n}'>
152 </tr> No newline at end of file
152 </tr>
@@ -1,117 +1,117 b''
1 ## Changesets table !
1 ## Changesets table !
2 <%namespace name="base" file="/base/base.mako"/>
2 <%namespace name="base" file="/base/base.mako"/>
3
3
4 %if c.ancestor:
4 %if c.ancestor:
5 <div class="ancestor">${_('Common Ancestor Commit')}:
5 <div class="ancestor">${_('Common Ancestor Commit')}:
6 <a href="${h.route_path('repo_commit', repo_name=c.repo_name, commit_id=c.ancestor)}">
6 <a href="${h.route_path('repo_commit', repo_name=c.repo_name, commit_id=c.ancestor)}">
7 ${h.short_id(c.ancestor)}
7 ${h.short_id(c.ancestor)}
8 </a>. ${_('Compare was calculated based on this shared commit.')}
8 </a>. ${_('Compare was calculated based on this shared commit.')}
9 <input id="common_ancestor" type="hidden" name="common_ancestor" value="${c.ancestor}">
9 <input id="common_ancestor" type="hidden" name="common_ancestor" value="${c.ancestor}">
10 </div>
10 </div>
11 %endif
11 %endif
12
12
13 <div class="container">
13 <div class="container">
14 <input type="hidden" name="__start__" value="revisions:sequence">
14 <input type="hidden" name="__start__" value="revisions:sequence">
15 <table class="rctable compare_view_commits">
15 <table class="rctable compare_view_commits">
16 <tr>
16 <tr>
17 <th>${_('Time')}</th>
17 <th>${_('Time')}</th>
18 <th>${_('Author')}</th>
18 <th>${_('Author')}</th>
19 <th>${_('Commit')}</th>
19 <th>${_('Commit')}</th>
20 <th></th>
20 <th></th>
21 <th>${_('Description')}</th>
21 <th>${_('Description')}</th>
22 </tr>
22 </tr>
23 ## to speed up lookups cache some functions before the loop
23 ## to speed up lookups cache some functions before the loop
24 <%
24 <%
25 active_patterns = h.get_active_pattern_entries(c.repo_name)
25 active_patterns = h.get_active_pattern_entries(c.repo_name)
26 urlify_commit_message = h.partial(h.urlify_commit_message, active_pattern_entries=active_patterns)
26 urlify_commit_message = h.partial(h.urlify_commit_message, active_pattern_entries=active_patterns)
27 %>
27 %>
28 %for commit in c.commit_ranges:
28 %for commit in c.commit_ranges:
29 <tr id="row-${commit.raw_id}"
29 <tr id="row-${commit.raw_id}"
30 commit_id="${commit.raw_id}"
30 commit_id="${commit.raw_id}"
31 class="compare_select"
31 class="compare_select"
32 style="${'display: none' if c.collapse_all_commits else ''}"
32 style="${'display: none' if c.collapse_all_commits else ''}"
33 >
33 >
34 <td class="td-time">
34 <td class="td-time">
35 ${h.age_component(commit.date)}
35 ${h.age_component(commit.date)}
36 </td>
36 </td>
37 <td class="td-user">
37 <td class="td-user">
38 ${base.gravatar_with_user(commit.author, 16)}
38 ${base.gravatar_with_user(commit.author, 16)}
39 </td>
39 </td>
40 <td class="td-hash">
40 <td class="td-hash">
41 <code>
41 <code>
42 <a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=commit.raw_id)}">
42 <a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=commit.raw_id)}">
43 r${commit.idx}:${h.short_id(commit.raw_id)}
43 r${commit.idx}:${h.short_id(commit.raw_id)}
44 </a>
44 </a>
45 ${h.hidden('revisions',commit.raw_id)}
45 ${h.hidden('revisions',commit.raw_id)}
46 </code>
46 </code>
47 </td>
47 </td>
48 <td class="expand_commit"
48 <td class="expand_commit"
49 data-commit-id="${commit.raw_id}"
49 data-commit-id="${commit.raw_id}"
50 title="${_( 'Expand commit message')}"
50 title="${_( 'Expand commit message')}"
51 >
51 >
52 <div class="show_more_col">
52 <div class="show_more_col">
53 <i class="show_more"></i>
53 <i class="icon-more-linked"></i>
54 </div>
54 </div>
55 </td>
55 </td>
56 <td class="mid td-description">
56 <td class="mid td-description">
57 <div class="log-container truncate-wrap">
57 <div class="log-container truncate-wrap">
58 <div
58 <div
59 id="c-${commit.raw_id}"
59 id="c-${commit.raw_id}"
60 class="message truncate"
60 class="message truncate"
61 data-message-raw="${commit.message}"
61 data-message-raw="${commit.message}"
62 >
62 >
63 ${urlify_commit_message(commit.message, c.repo_name)}
63 ${urlify_commit_message(commit.message, c.repo_name)}
64 </div>
64 </div>
65 </div>
65 </div>
66 </td>
66 </td>
67 </tr>
67 </tr>
68 %endfor
68 %endfor
69 <tr class="compare_select_hidden" style="${'' if c.collapse_all_commits else 'display: none'}">
69 <tr class="compare_select_hidden" style="${'' if c.collapse_all_commits else 'display: none'}">
70 <td colspan="5">
70 <td colspan="5">
71 ${_ungettext('%s commit hidden','%s commits hidden', len(c.commit_ranges)) % len(c.commit_ranges)},
71 ${_ungettext('%s commit hidden','%s commits hidden', len(c.commit_ranges)) % len(c.commit_ranges)},
72 <a href="#" onclick="$('.compare_select').show();$('.compare_select_hidden').hide(); return false">${_ungettext('show it','show them', len(c.commit_ranges))}</a>
72 <a href="#" onclick="$('.compare_select').show();$('.compare_select_hidden').hide(); return false">${_ungettext('show it','show them', len(c.commit_ranges))}</a>
73 </td>
73 </td>
74 </tr>
74 </tr>
75 % if not c.commit_ranges:
75 % if not c.commit_ranges:
76 <tr class="compare_select">
76 <tr class="compare_select">
77 <td colspan="5">
77 <td colspan="5">
78 ${_('No commits in this compare')}
78 ${_('No commits in this compare')}
79 </td>
79 </td>
80 </tr>
80 </tr>
81 % endif
81 % endif
82 </table>
82 </table>
83 <input type="hidden" name="__end__" value="revisions:sequence">
83 <input type="hidden" name="__end__" value="revisions:sequence">
84
84
85 </div>
85 </div>
86
86
87 <script>
87 <script>
88 $('.expand_commit').on('click',function(e){
88 $('.expand_commit').on('click',function(e){
89 var target_expand = $(this);
89 var target_expand = $(this);
90 var cid = target_expand.data('commitId');
90 var cid = target_expand.data('commitId');
91
91
92 // ## TODO: dan: extract styles into css, and just toggleClass('open') here
92 // ## TODO: dan: extract styles into css, and just toggleClass('open') here
93 if (target_expand.hasClass('open')){
93 if (target_expand.hasClass('open')){
94 $('#c-'+cid).css({
94 $('#c-'+cid).css({
95 'height': '1.5em',
95 'height': '1.5em',
96 'white-space': 'nowrap',
96 'white-space': 'nowrap',
97 'text-overflow': 'ellipsis',
97 'text-overflow': 'ellipsis',
98 'overflow':'hidden'
98 'overflow':'hidden'
99 });
99 });
100 target_expand.removeClass('open');
100 target_expand.removeClass('open');
101 }
101 }
102 else {
102 else {
103 $('#c-'+cid).css({
103 $('#c-'+cid).css({
104 'height': 'auto',
104 'height': 'auto',
105 'white-space': 'pre-line',
105 'white-space': 'pre-line',
106 'text-overflow': 'initial',
106 'text-overflow': 'initial',
107 'overflow':'visible'
107 'overflow':'visible'
108 });
108 });
109 target_expand.addClass('open');
109 target_expand.addClass('open');
110 }
110 }
111 });
111 });
112
112
113 $('.compare_select').on('click',function(e){
113 $('.compare_select').on('click',function(e){
114 var cid = $(this).attr('commit_id');
114 var cid = $(this).attr('commit_id');
115 $('#row-'+cid).toggleClass('hl', !$('#row-'+cid).hasClass('hl'));
115 $('#row-'+cid).toggleClass('hl', !$('#row-'+cid).hasClass('hl'));
116 });
116 });
117 </script>
117 </script>
@@ -1,874 +1,874 b''
1 <%inherit file="/base/base.mako"/>
1 <%inherit file="/base/base.mako"/>
2 <%namespace name="base" file="/base/base.mako"/>
2 <%namespace name="base" file="/base/base.mako"/>
3 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
3 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
4
4
5 <%def name="title()">
5 <%def name="title()">
6 ${_('%s Pull Request #%s') % (c.repo_name, c.pull_request.pull_request_id)}
6 ${_('%s Pull Request #%s') % (c.repo_name, c.pull_request.pull_request_id)}
7 %if c.rhodecode_name:
7 %if c.rhodecode_name:
8 &middot; ${h.branding(c.rhodecode_name)}
8 &middot; ${h.branding(c.rhodecode_name)}
9 %endif
9 %endif
10 </%def>
10 </%def>
11
11
12 <%def name="breadcrumbs_links()">
12 <%def name="breadcrumbs_links()">
13 <span id="pr-title">
13 <span id="pr-title">
14 ${c.pull_request.title}
14 ${c.pull_request.title}
15 %if c.pull_request.is_closed():
15 %if c.pull_request.is_closed():
16 (${_('Closed')})
16 (${_('Closed')})
17 %endif
17 %endif
18 </span>
18 </span>
19 <div id="pr-title-edit" class="input" style="display: none;">
19 <div id="pr-title-edit" class="input" style="display: none;">
20 ${h.text('pullrequest_title', id_="pr-title-input", class_="large", value=c.pull_request.title)}
20 ${h.text('pullrequest_title', id_="pr-title-input", class_="large", value=c.pull_request.title)}
21 </div>
21 </div>
22 </%def>
22 </%def>
23
23
24 <%def name="menu_bar_nav()">
24 <%def name="menu_bar_nav()">
25 ${self.menu_items(active='repositories')}
25 ${self.menu_items(active='repositories')}
26 </%def>
26 </%def>
27
27
28 <%def name="menu_bar_subnav()">
28 <%def name="menu_bar_subnav()">
29 ${self.repo_menu(active='showpullrequest')}
29 ${self.repo_menu(active='showpullrequest')}
30 </%def>
30 </%def>
31
31
32 <%def name="main()">
32 <%def name="main()">
33
33
34 <script type="text/javascript">
34 <script type="text/javascript">
35 // TODO: marcink switch this to pyroutes
35 // TODO: marcink switch this to pyroutes
36 AJAX_COMMENT_DELETE_URL = "${h.route_path('pullrequest_comment_delete',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id,comment_id='__COMMENT_ID__')}";
36 AJAX_COMMENT_DELETE_URL = "${h.route_path('pullrequest_comment_delete',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id,comment_id='__COMMENT_ID__')}";
37 templateContext.pull_request_data.pull_request_id = ${c.pull_request.pull_request_id};
37 templateContext.pull_request_data.pull_request_id = ${c.pull_request.pull_request_id};
38 </script>
38 </script>
39 <div class="box">
39 <div class="box">
40
40
41 <div class="title">
41 <div class="title">
42 ${self.repo_page_title(c.rhodecode_db_repo)}
42 ${self.repo_page_title(c.rhodecode_db_repo)}
43 </div>
43 </div>
44
44
45 ${self.breadcrumbs()}
45 ${self.breadcrumbs()}
46
46
47 <div class="box pr-summary">
47 <div class="box pr-summary">
48
48
49 <div class="summary-details block-left">
49 <div class="summary-details block-left">
50 <% summary = lambda n:{False:'summary-short'}.get(n) %>
50 <% summary = lambda n:{False:'summary-short'}.get(n) %>
51 <div class="pr-details-title">
51 <div class="pr-details-title">
52 <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 <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)}
53 %if c.allowed_to_update:
53 %if c.allowed_to_update:
54 <div id="delete_pullrequest" class="pull-right action_button ${'' if c.allowed_to_delete else 'disabled' }" style="clear:inherit;padding: 0">
54 <div id="delete_pullrequest" class="pull-right action_button ${'' if c.allowed_to_delete else 'disabled' }" style="clear:inherit;padding: 0">
55 % if c.allowed_to_delete:
55 % if c.allowed_to_delete:
56 ${h.secure_form(h.route_path('pullrequest_delete', repo_name=c.pull_request.target_repo.repo_name, pull_request_id=c.pull_request.pull_request_id), request=request)}
56 ${h.secure_form(h.route_path('pullrequest_delete', repo_name=c.pull_request.target_repo.repo_name, pull_request_id=c.pull_request.pull_request_id), request=request)}
57 ${h.submit('remove_%s' % c.pull_request.pull_request_id, _('Delete'),
57 ${h.submit('remove_%s' % c.pull_request.pull_request_id, _('Delete'),
58 class_="btn btn-link btn-danger no-margin",onclick="return confirm('"+_('Confirm to delete this pull request')+"');")}
58 class_="btn btn-link btn-danger no-margin",onclick="return confirm('"+_('Confirm to delete this pull request')+"');")}
59 ${h.end_form()}
59 ${h.end_form()}
60 % else:
60 % else:
61 ${_('Delete')}
61 ${_('Delete')}
62 % endif
62 % endif
63 </div>
63 </div>
64 <div id="open_edit_pullrequest" class="pull-right action_button">${_('Edit')}</div>
64 <div id="open_edit_pullrequest" class="pull-right action_button">${_('Edit')}</div>
65 <div id="close_edit_pullrequest" class="pull-right action_button" style="display: none;padding: 0">${_('Cancel')}</div>
65 <div id="close_edit_pullrequest" class="pull-right action_button" style="display: none;padding: 0">${_('Cancel')}</div>
66 %endif
66 %endif
67 </div>
67 </div>
68
68
69 <div id="summary" class="fields pr-details-content">
69 <div id="summary" class="fields pr-details-content">
70 <div class="field">
70 <div class="field">
71 <div class="label-summary">
71 <div class="label-summary">
72 <label>${_('Source')}:</label>
72 <label>${_('Source')}:</label>
73 </div>
73 </div>
74 <div class="input">
74 <div class="input">
75 <div class="pr-origininfo">
75 <div class="pr-origininfo">
76 ## branch link is only valid if it is a branch
76 ## branch link is only valid if it is a branch
77 <span class="tag">
77 <span class="tag">
78 %if c.pull_request.source_ref_parts.type == 'branch':
78 %if c.pull_request.source_ref_parts.type == 'branch':
79 <a href="${h.route_path('repo_changelog', repo_name=c.pull_request.source_repo.repo_name, _query=dict(branch=c.pull_request.source_ref_parts.name))}">${c.pull_request.source_ref_parts.type}: ${c.pull_request.source_ref_parts.name}</a>
79 <a href="${h.route_path('repo_changelog', repo_name=c.pull_request.source_repo.repo_name, _query=dict(branch=c.pull_request.source_ref_parts.name))}">${c.pull_request.source_ref_parts.type}: ${c.pull_request.source_ref_parts.name}</a>
80 %else:
80 %else:
81 ${c.pull_request.source_ref_parts.type}: ${c.pull_request.source_ref_parts.name}
81 ${c.pull_request.source_ref_parts.type}: ${c.pull_request.source_ref_parts.name}
82 %endif
82 %endif
83 </span>
83 </span>
84 <span class="clone-url">
84 <span class="clone-url">
85 <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 <a href="${h.route_path('repo_summary', repo_name=c.pull_request.source_repo.repo_name)}">${c.pull_request.source_repo.clone_url()}</a>
86 </span>
86 </span>
87 <br/>
87 <br/>
88 % if c.ancestor_commit:
88 % if c.ancestor_commit:
89 ${_('Common ancestor')}:
89 ${_('Common ancestor')}:
90 <code><a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=c.ancestor_commit.raw_id)}">${h.show_id(c.ancestor_commit)}</a></code>
90 <code><a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=c.ancestor_commit.raw_id)}">${h.show_id(c.ancestor_commit)}</a></code>
91 % endif
91 % endif
92 </div>
92 </div>
93 %if h.is_hg(c.pull_request.source_repo):
93 %if h.is_hg(c.pull_request.source_repo):
94 <% clone_url = 'hg pull -r {} {}'.format(h.short_id(c.source_ref), c.pull_request.source_repo.clone_url()) %>
94 <% clone_url = 'hg pull -r {} {}'.format(h.short_id(c.source_ref), c.pull_request.source_repo.clone_url()) %>
95 %elif h.is_git(c.pull_request.source_repo):
95 %elif h.is_git(c.pull_request.source_repo):
96 <% clone_url = 'git pull {} {}'.format(c.pull_request.source_repo.clone_url(), c.pull_request.source_ref_parts.name) %>
96 <% clone_url = 'git pull {} {}'.format(c.pull_request.source_repo.clone_url(), c.pull_request.source_ref_parts.name) %>
97 %endif
97 %endif
98
98
99 <div class="">
99 <div class="">
100 <input type="text" class="input-monospace pr-pullinfo" value="${clone_url}" readonly="readonly">
100 <input type="text" class="input-monospace pr-pullinfo" value="${clone_url}" readonly="readonly">
101 <i class="tooltip icon-clipboard clipboard-action pull-right pr-pullinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the pull url')}"></i>
101 <i class="tooltip icon-clipboard clipboard-action pull-right pr-pullinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the pull url')}"></i>
102 </div>
102 </div>
103
103
104 </div>
104 </div>
105 </div>
105 </div>
106 <div class="field">
106 <div class="field">
107 <div class="label-summary">
107 <div class="label-summary">
108 <label>${_('Target')}:</label>
108 <label>${_('Target')}:</label>
109 </div>
109 </div>
110 <div class="input">
110 <div class="input">
111 <div class="pr-targetinfo">
111 <div class="pr-targetinfo">
112 ## branch link is only valid if it is a branch
112 ## branch link is only valid if it is a branch
113 <span class="tag">
113 <span class="tag">
114 %if c.pull_request.target_ref_parts.type == 'branch':
114 %if c.pull_request.target_ref_parts.type == 'branch':
115 <a href="${h.route_path('repo_changelog', repo_name=c.pull_request.target_repo.repo_name, _query=dict(branch=c.pull_request.target_ref_parts.name))}">${c.pull_request.target_ref_parts.type}: ${c.pull_request.target_ref_parts.name}</a>
115 <a href="${h.route_path('repo_changelog', repo_name=c.pull_request.target_repo.repo_name, _query=dict(branch=c.pull_request.target_ref_parts.name))}">${c.pull_request.target_ref_parts.type}: ${c.pull_request.target_ref_parts.name}</a>
116 %else:
116 %else:
117 ${c.pull_request.target_ref_parts.type}: ${c.pull_request.target_ref_parts.name}
117 ${c.pull_request.target_ref_parts.type}: ${c.pull_request.target_ref_parts.name}
118 %endif
118 %endif
119 </span>
119 </span>
120 <span class="clone-url">
120 <span class="clone-url">
121 <a href="${h.route_path('repo_summary', repo_name=c.pull_request.target_repo.repo_name)}">${c.pull_request.target_repo.clone_url()}</a>
121 <a href="${h.route_path('repo_summary', repo_name=c.pull_request.target_repo.repo_name)}">${c.pull_request.target_repo.clone_url()}</a>
122 </span>
122 </span>
123 </div>
123 </div>
124 </div>
124 </div>
125 </div>
125 </div>
126
126
127 ## Link to the shadow repository.
127 ## Link to the shadow repository.
128 <div class="field">
128 <div class="field">
129 <div class="label-summary">
129 <div class="label-summary">
130 <label>${_('Merge')}:</label>
130 <label>${_('Merge')}:</label>
131 </div>
131 </div>
132 <div class="input">
132 <div class="input">
133 % if not c.pull_request.is_closed() and c.pull_request.shadow_merge_ref:
133 % if not c.pull_request.is_closed() and c.pull_request.shadow_merge_ref:
134 %if h.is_hg(c.pull_request.target_repo):
134 %if h.is_hg(c.pull_request.target_repo):
135 <% clone_url = 'hg clone --update {} {} pull-request-{}'.format(c.pull_request.shadow_merge_ref.name, c.shadow_clone_url, c.pull_request.pull_request_id) %>
135 <% clone_url = 'hg clone --update {} {} pull-request-{}'.format(c.pull_request.shadow_merge_ref.name, c.shadow_clone_url, c.pull_request.pull_request_id) %>
136 %elif h.is_git(c.pull_request.target_repo):
136 %elif h.is_git(c.pull_request.target_repo):
137 <% clone_url = 'git clone --branch {} {} pull-request-{}'.format(c.pull_request.shadow_merge_ref.name, c.shadow_clone_url, c.pull_request.pull_request_id) %>
137 <% clone_url = 'git clone --branch {} {} pull-request-{}'.format(c.pull_request.shadow_merge_ref.name, c.shadow_clone_url, c.pull_request.pull_request_id) %>
138 %endif
138 %endif
139 <div class="">
139 <div class="">
140 <input type="text" class="input-monospace pr-mergeinfo" value="${clone_url}" readonly="readonly">
140 <input type="text" class="input-monospace pr-mergeinfo" value="${clone_url}" readonly="readonly">
141 <i class="tooltip icon-clipboard clipboard-action pull-right pr-mergeinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the clone url')}"></i>
141 <i class="tooltip icon-clipboard clipboard-action pull-right pr-mergeinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the clone url')}"></i>
142 </div>
142 </div>
143 % else:
143 % else:
144 <div class="">
144 <div class="">
145 ${_('Shadow repository data not available')}.
145 ${_('Shadow repository data not available')}.
146 </div>
146 </div>
147 % endif
147 % endif
148 </div>
148 </div>
149 </div>
149 </div>
150
150
151 <div class="field">
151 <div class="field">
152 <div class="label-summary">
152 <div class="label-summary">
153 <label>${_('Review')}:</label>
153 <label>${_('Review')}:</label>
154 </div>
154 </div>
155 <div class="input">
155 <div class="input">
156 %if c.pull_request_review_status:
156 %if c.pull_request_review_status:
157 <div class="${'flag_status %s' % c.pull_request_review_status} tooltip pull-left"></div>
157 <div class="${'flag_status %s' % c.pull_request_review_status} tooltip pull-left"></div>
158 <span class="changeset-status-lbl tooltip">
158 <span class="changeset-status-lbl tooltip">
159 %if c.pull_request.is_closed():
159 %if c.pull_request.is_closed():
160 ${_('Closed')},
160 ${_('Closed')},
161 %endif
161 %endif
162 ${h.commit_status_lbl(c.pull_request_review_status)}
162 ${h.commit_status_lbl(c.pull_request_review_status)}
163 </span>
163 </span>
164 - ${_ungettext('calculated based on %s reviewer vote', 'calculated based on %s reviewers votes', len(c.pull_request_reviewers)) % len(c.pull_request_reviewers)}
164 - ${_ungettext('calculated based on %s reviewer vote', 'calculated based on %s reviewers votes', len(c.pull_request_reviewers)) % len(c.pull_request_reviewers)}
165 %endif
165 %endif
166 </div>
166 </div>
167 </div>
167 </div>
168 <div class="field">
168 <div class="field">
169 <div class="pr-description-label label-summary" title="${_('Rendered using {} renderer').format(c.renderer)}">
169 <div class="pr-description-label label-summary" title="${_('Rendered using {} renderer').format(c.renderer)}">
170 <label>${_('Description')}:</label>
170 <label>${_('Description')}:</label>
171 </div>
171 </div>
172 <div id="pr-desc" class="input">
172 <div id="pr-desc" class="input">
173 <div class="pr-description">${h.render(c.pull_request.description, renderer=c.renderer)}</div>
173 <div class="pr-description">${h.render(c.pull_request.description, renderer=c.renderer)}</div>
174 </div>
174 </div>
175 <div id="pr-desc-edit" class="input textarea editor" style="display: none;">
175 <div id="pr-desc-edit" class="input textarea editor" style="display: none;">
176 <input id="pr-renderer-input" type="hidden" name="description_renderer" value="${c.visual.default_renderer}">
176 <input id="pr-renderer-input" type="hidden" name="description_renderer" value="${c.visual.default_renderer}">
177 ${dt.markup_form('pr-description-input', form_text=c.pull_request.description)}
177 ${dt.markup_form('pr-description-input', form_text=c.pull_request.description)}
178 </div>
178 </div>
179 </div>
179 </div>
180
180
181 <div class="field">
181 <div class="field">
182 <div class="label-summary">
182 <div class="label-summary">
183 <label>${_('Versions')}:</label>
183 <label>${_('Versions')}:</label>
184 </div>
184 </div>
185
185
186 <% outdated_comm_count_ver = len(c.inline_versions[None]['outdated']) %>
186 <% outdated_comm_count_ver = len(c.inline_versions[None]['outdated']) %>
187 <% general_outdated_comm_count_ver = len(c.comment_versions[None]['outdated']) %>
187 <% general_outdated_comm_count_ver = len(c.comment_versions[None]['outdated']) %>
188
188
189 <div class="pr-versions">
189 <div class="pr-versions">
190 % if c.show_version_changes:
190 % if c.show_version_changes:
191 <% outdated_comm_count_ver = len(c.inline_versions[c.at_version_num]['outdated']) %>
191 <% outdated_comm_count_ver = len(c.inline_versions[c.at_version_num]['outdated']) %>
192 <% general_outdated_comm_count_ver = len(c.comment_versions[c.at_version_num]['outdated']) %>
192 <% general_outdated_comm_count_ver = len(c.comment_versions[c.at_version_num]['outdated']) %>
193 <a id="show-pr-versions" class="input" onclick="return versionController.toggleVersionView(this)" href="#show-pr-versions"
193 <a id="show-pr-versions" class="input" onclick="return versionController.toggleVersionView(this)" href="#show-pr-versions"
194 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))}"
194 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))}"
195 data-toggle-off="${_('Hide all versions of this pull request')}">
195 data-toggle-off="${_('Hide all versions of this pull request')}">
196 ${_ungettext('{} version available for this pull request, show it.', '{} versions available for this pull request, show them.', len(c.versions)).format(len(c.versions))}
196 ${_ungettext('{} version available for this pull request, show it.', '{} versions available for this pull request, show them.', len(c.versions)).format(len(c.versions))}
197 </a>
197 </a>
198 <table>
198 <table>
199 ## SHOW ALL VERSIONS OF PR
199 ## SHOW ALL VERSIONS OF PR
200 <% ver_pr = None %>
200 <% ver_pr = None %>
201
201
202 % for data in reversed(list(enumerate(c.versions, 1))):
202 % for data in reversed(list(enumerate(c.versions, 1))):
203 <% ver_pos = data[0] %>
203 <% ver_pos = data[0] %>
204 <% ver = data[1] %>
204 <% ver = data[1] %>
205 <% ver_pr = ver.pull_request_version_id %>
205 <% ver_pr = ver.pull_request_version_id %>
206 <% display_row = '' if c.at_version and (c.at_version_num == ver_pr or c.from_version_num == ver_pr) else 'none' %>
206 <% display_row = '' if c.at_version and (c.at_version_num == ver_pr or c.from_version_num == ver_pr) else 'none' %>
207
207
208 <tr class="version-pr" style="display: ${display_row}">
208 <tr class="version-pr" style="display: ${display_row}">
209 <td>
209 <td>
210 <code>
210 <code>
211 <a href="${request.current_route_path(_query=dict(version=ver_pr or 'latest'))}">v${ver_pos}</a>
211 <a href="${request.current_route_path(_query=dict(version=ver_pr or 'latest'))}">v${ver_pos}</a>
212 </code>
212 </code>
213 </td>
213 </td>
214 <td>
214 <td>
215 <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}"/>
215 <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}"/>
216 <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}"/>
216 <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}"/>
217 </td>
217 </td>
218 <td>
218 <td>
219 <% review_status = c.review_versions[ver_pr].status if ver_pr in c.review_versions else 'not_reviewed' %>
219 <% review_status = c.review_versions[ver_pr].status if ver_pr in c.review_versions else 'not_reviewed' %>
220 <div class="${'flag_status %s' % review_status} tooltip pull-left" title="${_('Your review status at this version')}">
220 <div class="${'flag_status %s' % review_status} tooltip pull-left" title="${_('Your review status at this version')}">
221 </div>
221 </div>
222 </td>
222 </td>
223 <td>
223 <td>
224 % if c.at_version_num != ver_pr:
224 % if c.at_version_num != ver_pr:
225 <i class="icon-comment"></i>
225 <i class="icon-comment"></i>
226 <code class="tooltip" title="${_('Comment from pull request version v{0}, general:{1} inline:{2}').format(ver_pos, len(c.comment_versions[ver_pr]['at']), len(c.inline_versions[ver_pr]['at']))}">
226 <code class="tooltip" title="${_('Comment from pull request version v{0}, general:{1} inline:{2}').format(ver_pos, len(c.comment_versions[ver_pr]['at']), len(c.inline_versions[ver_pr]['at']))}">
227 G:${len(c.comment_versions[ver_pr]['at'])} / I:${len(c.inline_versions[ver_pr]['at'])}
227 G:${len(c.comment_versions[ver_pr]['at'])} / I:${len(c.inline_versions[ver_pr]['at'])}
228 </code>
228 </code>
229 % endif
229 % endif
230 </td>
230 </td>
231 <td>
231 <td>
232 ##<code>${ver.source_ref_parts.commit_id[:6]}</code>
232 ##<code>${ver.source_ref_parts.commit_id[:6]}</code>
233 </td>
233 </td>
234 <td>
234 <td>
235 ${h.age_component(ver.updated_on, time_is_local=True)}
235 ${h.age_component(ver.updated_on, time_is_local=True)}
236 </td>
236 </td>
237 </tr>
237 </tr>
238 % endfor
238 % endfor
239
239
240 <tr>
240 <tr>
241 <td colspan="6">
241 <td colspan="6">
242 <button id="show-version-diff" onclick="return versionController.showVersionDiff()" class="btn btn-sm" style="display: none"
242 <button id="show-version-diff" onclick="return versionController.showVersionDiff()" class="btn btn-sm" style="display: none"
243 data-label-text-locked="${_('select versions to show changes')}"
243 data-label-text-locked="${_('select versions to show changes')}"
244 data-label-text-diff="${_('show changes between versions')}"
244 data-label-text-diff="${_('show changes between versions')}"
245 data-label-text-show="${_('show pull request for this version')}"
245 data-label-text-show="${_('show pull request for this version')}"
246 >
246 >
247 ${_('select versions to show changes')}
247 ${_('select versions to show changes')}
248 </button>
248 </button>
249 </td>
249 </td>
250 </tr>
250 </tr>
251
251
252 ## show comment/inline comments summary
252 ## show comment/inline comments summary
253 <%def name="comments_summary()">
253 <%def name="comments_summary()">
254 <tr>
254 <tr>
255 <td colspan="6" class="comments-summary-td">
255 <td colspan="6" class="comments-summary-td">
256
256
257 % if c.at_version:
257 % if c.at_version:
258 <% inline_comm_count_ver = len(c.inline_versions[c.at_version_num]['display']) %>
258 <% inline_comm_count_ver = len(c.inline_versions[c.at_version_num]['display']) %>
259 <% general_comm_count_ver = len(c.comment_versions[c.at_version_num]['display']) %>
259 <% general_comm_count_ver = len(c.comment_versions[c.at_version_num]['display']) %>
260 ${_('Comments at this version')}:
260 ${_('Comments at this version')}:
261 % else:
261 % else:
262 <% inline_comm_count_ver = len(c.inline_versions[c.at_version_num]['until']) %>
262 <% inline_comm_count_ver = len(c.inline_versions[c.at_version_num]['until']) %>
263 <% general_comm_count_ver = len(c.comment_versions[c.at_version_num]['until']) %>
263 <% general_comm_count_ver = len(c.comment_versions[c.at_version_num]['until']) %>
264 ${_('Comments for this pull request')}:
264 ${_('Comments for this pull request')}:
265 % endif
265 % endif
266
266
267
267
268 %if general_comm_count_ver:
268 %if general_comm_count_ver:
269 <a href="#comments">${_("%d General ") % general_comm_count_ver}</a>
269 <a href="#comments">${_("%d General ") % general_comm_count_ver}</a>
270 %else:
270 %else:
271 ${_("%d General ") % general_comm_count_ver}
271 ${_("%d General ") % general_comm_count_ver}
272 %endif
272 %endif
273
273
274 %if inline_comm_count_ver:
274 %if inline_comm_count_ver:
275 , <a href="#" onclick="return Rhodecode.comments.nextComment();" id="inline-comments-counter">${_("%d Inline") % inline_comm_count_ver}</a>
275 , <a href="#" onclick="return Rhodecode.comments.nextComment();" id="inline-comments-counter">${_("%d Inline") % inline_comm_count_ver}</a>
276 %else:
276 %else:
277 , ${_("%d Inline") % inline_comm_count_ver}
277 , ${_("%d Inline") % inline_comm_count_ver}
278 %endif
278 %endif
279
279
280 %if outdated_comm_count_ver:
280 %if outdated_comm_count_ver:
281 , <a href="#" onclick="showOutdated(); Rhodecode.comments.nextOutdatedComment(); return false;">${_("%d Outdated") % outdated_comm_count_ver}</a>
281 , <a href="#" onclick="showOutdated(); Rhodecode.comments.nextOutdatedComment(); return false;">${_("%d Outdated") % outdated_comm_count_ver}</a>
282 <a href="#" class="showOutdatedComments" onclick="showOutdated(this); return false;"> | ${_('show outdated comments')}</a>
282 <a href="#" class="showOutdatedComments" onclick="showOutdated(this); return false;"> | ${_('show outdated comments')}</a>
283 <a href="#" class="hideOutdatedComments" style="display: none" onclick="hideOutdated(this); return false;"> | ${_('hide outdated comments')}</a>
283 <a href="#" class="hideOutdatedComments" style="display: none" onclick="hideOutdated(this); return false;"> | ${_('hide outdated comments')}</a>
284 %else:
284 %else:
285 , ${_("%d Outdated") % outdated_comm_count_ver}
285 , ${_("%d Outdated") % outdated_comm_count_ver}
286 %endif
286 %endif
287 </td>
287 </td>
288 </tr>
288 </tr>
289 </%def>
289 </%def>
290 ${comments_summary()}
290 ${comments_summary()}
291 </table>
291 </table>
292 % else:
292 % else:
293 <div class="input">
293 <div class="input">
294 ${_('Pull request versions not available')}.
294 ${_('Pull request versions not available')}.
295 </div>
295 </div>
296 <div>
296 <div>
297 <table>
297 <table>
298 ${comments_summary()}
298 ${comments_summary()}
299 </table>
299 </table>
300 </div>
300 </div>
301 % endif
301 % endif
302 </div>
302 </div>
303 </div>
303 </div>
304
304
305 <div id="pr-save" class="field" style="display: none;">
305 <div id="pr-save" class="field" style="display: none;">
306 <div class="label-summary"></div>
306 <div class="label-summary"></div>
307 <div class="input">
307 <div class="input">
308 <span id="edit_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</span>
308 <span id="edit_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</span>
309 </div>
309 </div>
310 </div>
310 </div>
311 </div>
311 </div>
312 </div>
312 </div>
313 <div>
313 <div>
314 ## AUTHOR
314 ## AUTHOR
315 <div class="reviewers-title block-right">
315 <div class="reviewers-title block-right">
316 <div class="pr-details-title">
316 <div class="pr-details-title">
317 ${_('Author of this pull request')}
317 ${_('Author of this pull request')}
318 </div>
318 </div>
319 </div>
319 </div>
320 <div class="block-right pr-details-content reviewers">
320 <div class="block-right pr-details-content reviewers">
321 <ul class="group_members">
321 <ul class="group_members">
322 <li>
322 <li>
323 ${self.gravatar_with_user(c.pull_request.author.email, 16)}
323 ${self.gravatar_with_user(c.pull_request.author.email, 16)}
324 </li>
324 </li>
325 </ul>
325 </ul>
326 </div>
326 </div>
327
327
328 ## REVIEW RULES
328 ## REVIEW RULES
329 <div id="review_rules" style="display: none" class="reviewers-title block-right">
329 <div id="review_rules" style="display: none" class="reviewers-title block-right">
330 <div class="pr-details-title">
330 <div class="pr-details-title">
331 ${_('Reviewer rules')}
331 ${_('Reviewer rules')}
332 %if c.allowed_to_update:
332 %if c.allowed_to_update:
333 <span id="close_edit_reviewers" class="block-right action_button last-item" style="display: none;">${_('Close')}</span>
333 <span id="close_edit_reviewers" class="block-right action_button last-item" style="display: none;">${_('Close')}</span>
334 %endif
334 %endif
335 </div>
335 </div>
336 <div class="pr-reviewer-rules">
336 <div class="pr-reviewer-rules">
337 ## review rules will be appended here, by default reviewers logic
337 ## review rules will be appended here, by default reviewers logic
338 </div>
338 </div>
339 <input id="review_data" type="hidden" name="review_data" value="">
339 <input id="review_data" type="hidden" name="review_data" value="">
340 </div>
340 </div>
341
341
342 ## REVIEWERS
342 ## REVIEWERS
343 <div class="reviewers-title block-right">
343 <div class="reviewers-title block-right">
344 <div class="pr-details-title">
344 <div class="pr-details-title">
345 ${_('Pull request reviewers')}
345 ${_('Pull request reviewers')}
346 %if c.allowed_to_update:
346 %if c.allowed_to_update:
347 <span id="open_edit_reviewers" class="block-right action_button last-item">${_('Edit')}</span>
347 <span id="open_edit_reviewers" class="block-right action_button last-item">${_('Edit')}</span>
348 %endif
348 %endif
349 </div>
349 </div>
350 </div>
350 </div>
351 <div id="reviewers" class="block-right pr-details-content reviewers">
351 <div id="reviewers" class="block-right pr-details-content reviewers">
352
352
353 ## members redering block
353 ## members redering block
354 <input type="hidden" name="__start__" value="review_members:sequence">
354 <input type="hidden" name="__start__" value="review_members:sequence">
355 <ul id="review_members" class="group_members">
355 <ul id="review_members" class="group_members">
356
356
357 % for review_obj, member, reasons, mandatory, status in c.pull_request_reviewers:
357 % for review_obj, member, reasons, mandatory, status in c.pull_request_reviewers:
358 <script>
358 <script>
359 var member = ${h.json.dumps(h.reviewer_as_json(member, reasons=reasons, mandatory=mandatory, user_group=review_obj.rule_user_group_data()))|n};
359 var member = ${h.json.dumps(h.reviewer_as_json(member, reasons=reasons, mandatory=mandatory, user_group=review_obj.rule_user_group_data()))|n};
360 var status = "${(status[0][1].status if status else 'not_reviewed')}";
360 var status = "${(status[0][1].status if status else 'not_reviewed')}";
361 var status_lbl = "${h.commit_status_lbl(status[0][1].status if status else 'not_reviewed')}";
361 var status_lbl = "${h.commit_status_lbl(status[0][1].status if status else 'not_reviewed')}";
362 var allowed_to_update = ${h.json.dumps(c.allowed_to_update)};
362 var allowed_to_update = ${h.json.dumps(c.allowed_to_update)};
363
363
364 var entry = renderTemplate('reviewMemberEntry', {
364 var entry = renderTemplate('reviewMemberEntry', {
365 'member': member,
365 'member': member,
366 'mandatory': member.mandatory,
366 'mandatory': member.mandatory,
367 'reasons': member.reasons,
367 'reasons': member.reasons,
368 'allowed_to_update': allowed_to_update,
368 'allowed_to_update': allowed_to_update,
369 'review_status': status,
369 'review_status': status,
370 'review_status_label': status_lbl,
370 'review_status_label': status_lbl,
371 'user_group': member.user_group,
371 'user_group': member.user_group,
372 'create': false
372 'create': false
373 });
373 });
374 $('#review_members').append(entry)
374 $('#review_members').append(entry)
375 </script>
375 </script>
376
376
377 % endfor
377 % endfor
378
378
379 </ul>
379 </ul>
380 <input type="hidden" name="__end__" value="review_members:sequence">
380 <input type="hidden" name="__end__" value="review_members:sequence">
381 ## end members redering block
381 ## end members redering block
382
382
383 %if not c.pull_request.is_closed():
383 %if not c.pull_request.is_closed():
384 <div id="add_reviewer" class="ac" style="display: none;">
384 <div id="add_reviewer" class="ac" style="display: none;">
385 %if c.allowed_to_update:
385 %if c.allowed_to_update:
386 % if not c.forbid_adding_reviewers:
386 % if not c.forbid_adding_reviewers:
387 <div id="add_reviewer_input" class="reviewer_ac">
387 <div id="add_reviewer_input" class="reviewer_ac">
388 ${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))}
388 ${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))}
389 <div id="reviewers_container"></div>
389 <div id="reviewers_container"></div>
390 </div>
390 </div>
391 % endif
391 % endif
392 <div class="pull-right">
392 <div class="pull-right">
393 <button id="update_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</button>
393 <button id="update_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</button>
394 </div>
394 </div>
395 %endif
395 %endif
396 </div>
396 </div>
397 %endif
397 %endif
398 </div>
398 </div>
399 </div>
399 </div>
400 </div>
400 </div>
401 <div class="box">
401 <div class="box">
402 ##DIFF
402 ##DIFF
403 <div class="table" >
403 <div class="table" >
404 <div id="changeset_compare_view_content">
404 <div id="changeset_compare_view_content">
405 ##CS
405 ##CS
406 % if c.missing_requirements:
406 % if c.missing_requirements:
407 <div class="box">
407 <div class="box">
408 <div class="alert alert-warning">
408 <div class="alert alert-warning">
409 <div>
409 <div>
410 <strong>${_('Missing requirements:')}</strong>
410 <strong>${_('Missing requirements:')}</strong>
411 ${_('These commits cannot be displayed, because this repository uses the Mercurial largefiles extension, which was not enabled.')}
411 ${_('These commits cannot be displayed, because this repository uses the Mercurial largefiles extension, which was not enabled.')}
412 </div>
412 </div>
413 </div>
413 </div>
414 </div>
414 </div>
415 % elif c.missing_commits:
415 % elif c.missing_commits:
416 <div class="box">
416 <div class="box">
417 <div class="alert alert-warning">
417 <div class="alert alert-warning">
418 <div>
418 <div>
419 <strong>${_('Missing commits')}:</strong>
419 <strong>${_('Missing commits')}:</strong>
420 ${_('This pull request cannot be displayed, because one or more commits no longer exist in the source repository.')}
420 ${_('This pull request cannot be displayed, because one or more commits no longer exist in the source repository.')}
421 ${_('Please update this pull request, push the commits back into the source repository, or consider closing this pull request.')}
421 ${_('Please update this pull request, push the commits back into the source repository, or consider closing this pull request.')}
422 ${_('Consider doing a {force_refresh_url} in case you think this is an error.').format(force_refresh_url=h.link_to('force refresh', h.current_route_path(request, force_refresh='1')))|n}
422 ${_('Consider doing a {force_refresh_url} in case you think this is an error.').format(force_refresh_url=h.link_to('force refresh', h.current_route_path(request, force_refresh='1')))|n}
423 </div>
423 </div>
424 </div>
424 </div>
425 </div>
425 </div>
426 % endif
426 % endif
427
427
428 <div class="compare_view_commits_title">
428 <div class="compare_view_commits_title">
429 % if not c.compare_mode:
429 % if not c.compare_mode:
430
430
431 % if c.at_version_pos:
431 % if c.at_version_pos:
432 <h4>
432 <h4>
433 ${_('Showing changes at v%d, commenting is disabled.') % c.at_version_pos}
433 ${_('Showing changes at v%d, commenting is disabled.') % c.at_version_pos}
434 </h4>
434 </h4>
435 % endif
435 % endif
436
436
437 <div class="pull-left">
437 <div class="pull-left">
438 <div class="btn-group">
438 <div class="btn-group">
439 <a
439 <a
440 class="btn"
440 class="btn"
441 href="#"
441 href="#"
442 onclick="$('.compare_select').show();$('.compare_select_hidden').hide(); return false">
442 onclick="$('.compare_select').show();$('.compare_select_hidden').hide(); return false">
443 ${_ungettext('Expand %s commit','Expand %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
443 ${_ungettext('Expand %s commit','Expand %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
444 </a>
444 </a>
445 <a
445 <a
446 class="btn"
446 class="btn"
447 href="#"
447 href="#"
448 onclick="$('.compare_select').hide();$('.compare_select_hidden').show(); return false">
448 onclick="$('.compare_select').hide();$('.compare_select_hidden').show(); return false">
449 ${_ungettext('Collapse %s commit','Collapse %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
449 ${_ungettext('Collapse %s commit','Collapse %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
450 </a>
450 </a>
451 </div>
451 </div>
452 </div>
452 </div>
453
453
454 <div class="pull-right">
454 <div class="pull-right">
455 % if c.allowed_to_update and not c.pull_request.is_closed():
455 % if c.allowed_to_update and not c.pull_request.is_closed():
456 <a id="update_commits" class="btn btn-primary no-margin pull-right">${_('Update commits')}</a>
456 <a id="update_commits" class="btn btn-primary no-margin pull-right">${_('Update commits')}</a>
457 % else:
457 % else:
458 <a class="tooltip btn disabled pull-right" disabled="disabled" title="${_('Update is disabled for current view')}">${_('Update commits')}</a>
458 <a class="tooltip btn disabled pull-right" disabled="disabled" title="${_('Update is disabled for current view')}">${_('Update commits')}</a>
459 % endif
459 % endif
460
460
461 </div>
461 </div>
462 % endif
462 % endif
463 </div>
463 </div>
464
464
465 % if not c.missing_commits:
465 % if not c.missing_commits:
466 % if c.compare_mode:
466 % if c.compare_mode:
467 % if c.at_version:
467 % if c.at_version:
468 <h4>
468 <h4>
469 ${_('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')}:
469 ${_('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')}:
470 </h4>
470 </h4>
471
471
472 <div class="subtitle-compare">
472 <div class="subtitle-compare">
473 ${_('commits added: {}, removed: {}').format(len(c.commit_changes_summary.added), len(c.commit_changes_summary.removed))}
473 ${_('commits added: {}, removed: {}').format(len(c.commit_changes_summary.added), len(c.commit_changes_summary.removed))}
474 </div>
474 </div>
475
475
476 <div class="container">
476 <div class="container">
477 <table class="rctable compare_view_commits">
477 <table class="rctable compare_view_commits">
478 <tr>
478 <tr>
479 <th></th>
479 <th></th>
480 <th>${_('Time')}</th>
480 <th>${_('Time')}</th>
481 <th>${_('Author')}</th>
481 <th>${_('Author')}</th>
482 <th>${_('Commit')}</th>
482 <th>${_('Commit')}</th>
483 <th></th>
483 <th></th>
484 <th>${_('Description')}</th>
484 <th>${_('Description')}</th>
485 </tr>
485 </tr>
486
486
487 % for c_type, commit in c.commit_changes:
487 % for c_type, commit in c.commit_changes:
488 % if c_type in ['a', 'r']:
488 % if c_type in ['a', 'r']:
489 <%
489 <%
490 if c_type == 'a':
490 if c_type == 'a':
491 cc_title = _('Commit added in displayed changes')
491 cc_title = _('Commit added in displayed changes')
492 elif c_type == 'r':
492 elif c_type == 'r':
493 cc_title = _('Commit removed in displayed changes')
493 cc_title = _('Commit removed in displayed changes')
494 else:
494 else:
495 cc_title = ''
495 cc_title = ''
496 %>
496 %>
497 <tr id="row-${commit.raw_id}" commit_id="${commit.raw_id}" class="compare_select">
497 <tr id="row-${commit.raw_id}" commit_id="${commit.raw_id}" class="compare_select">
498 <td>
498 <td>
499 <div class="commit-change-indicator color-${c_type}-border">
499 <div class="commit-change-indicator color-${c_type}-border">
500 <div class="commit-change-content color-${c_type} tooltip" title="${h.tooltip(cc_title)}">
500 <div class="commit-change-content color-${c_type} tooltip" title="${h.tooltip(cc_title)}">
501 ${c_type.upper()}
501 ${c_type.upper()}
502 </div>
502 </div>
503 </div>
503 </div>
504 </td>
504 </td>
505 <td class="td-time">
505 <td class="td-time">
506 ${h.age_component(commit.date)}
506 ${h.age_component(commit.date)}
507 </td>
507 </td>
508 <td class="td-user">
508 <td class="td-user">
509 ${base.gravatar_with_user(commit.author, 16)}
509 ${base.gravatar_with_user(commit.author, 16)}
510 </td>
510 </td>
511 <td class="td-hash">
511 <td class="td-hash">
512 <code>
512 <code>
513 <a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=commit.raw_id)}">
513 <a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=commit.raw_id)}">
514 r${commit.idx}:${h.short_id(commit.raw_id)}
514 r${commit.idx}:${h.short_id(commit.raw_id)}
515 </a>
515 </a>
516 ${h.hidden('revisions', commit.raw_id)}
516 ${h.hidden('revisions', commit.raw_id)}
517 </code>
517 </code>
518 </td>
518 </td>
519 <td class="expand_commit" data-commit-id="${commit.raw_id}" title="${_( 'Expand commit message')}">
519 <td class="expand_commit" data-commit-id="${commit.raw_id}" title="${_( 'Expand commit message')}">
520 <div class="show_more_col">
520 <div class="show_more_col">
521 <i class="show_more"></i>
521 <i class="icon-more-linked"></i>
522 </div>
522 </div>
523 </td>
523 </td>
524 <td class="mid td-description">
524 <td class="mid td-description">
525 <div class="log-container truncate-wrap">
525 <div class="log-container truncate-wrap">
526 <div class="message truncate" id="c-${commit.raw_id}" data-message-raw="${commit.message}">
526 <div class="message truncate" id="c-${commit.raw_id}" data-message-raw="${commit.message}">
527 ${h.urlify_commit_message(commit.message, c.repo_name)}
527 ${h.urlify_commit_message(commit.message, c.repo_name)}
528 </div>
528 </div>
529 </div>
529 </div>
530 </td>
530 </td>
531 </tr>
531 </tr>
532 % endif
532 % endif
533 % endfor
533 % endfor
534 </table>
534 </table>
535 </div>
535 </div>
536
536
537 <script>
537 <script>
538 $('.expand_commit').on('click',function(e){
538 $('.expand_commit').on('click',function(e){
539 var target_expand = $(this);
539 var target_expand = $(this);
540 var cid = target_expand.data('commitId');
540 var cid = target_expand.data('commitId');
541
541
542 if (target_expand.hasClass('open')){
542 if (target_expand.hasClass('open')){
543 $('#c-'+cid).css({
543 $('#c-'+cid).css({
544 'height': '1.5em',
544 'height': '1.5em',
545 'white-space': 'nowrap',
545 'white-space': 'nowrap',
546 'text-overflow': 'ellipsis',
546 'text-overflow': 'ellipsis',
547 'overflow':'hidden'
547 'overflow':'hidden'
548 });
548 });
549 target_expand.removeClass('open');
549 target_expand.removeClass('open');
550 }
550 }
551 else {
551 else {
552 $('#c-'+cid).css({
552 $('#c-'+cid).css({
553 'height': 'auto',
553 'height': 'auto',
554 'white-space': 'pre-line',
554 'white-space': 'pre-line',
555 'text-overflow': 'initial',
555 'text-overflow': 'initial',
556 'overflow':'visible'
556 'overflow':'visible'
557 });
557 });
558 target_expand.addClass('open');
558 target_expand.addClass('open');
559 }
559 }
560 });
560 });
561 </script>
561 </script>
562
562
563 % endif
563 % endif
564
564
565 % else:
565 % else:
566 <%include file="/compare/compare_commits.mako" />
566 <%include file="/compare/compare_commits.mako" />
567 % endif
567 % endif
568
568
569 <div class="cs_files">
569 <div class="cs_files">
570 <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/>
570 <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/>
571
571
572 ${cbdiffs.render_diffset_menu(c.diffset, range_diff_on=c.range_diff_on)}
572 ${cbdiffs.render_diffset_menu(c.diffset, range_diff_on=c.range_diff_on)}
573
573
574 % if c.range_diff_on:
574 % if c.range_diff_on:
575 % for commit in c.commit_ranges:
575 % for commit in c.commit_ranges:
576 ${cbdiffs.render_diffset(
576 ${cbdiffs.render_diffset(
577 c.changes[commit.raw_id],
577 c.changes[commit.raw_id],
578 commit=commit, use_comments=True,
578 commit=commit, use_comments=True,
579 collapse_when_files_over=5,
579 collapse_when_files_over=5,
580 disable_new_comments=True,
580 disable_new_comments=True,
581 deleted_files_comments=c.deleted_files_comments,
581 deleted_files_comments=c.deleted_files_comments,
582 inline_comments=c.inline_comments)}
582 inline_comments=c.inline_comments)}
583 % endfor
583 % endfor
584 % else:
584 % else:
585 ${cbdiffs.render_diffset(
585 ${cbdiffs.render_diffset(
586 c.diffset, use_comments=True,
586 c.diffset, use_comments=True,
587 collapse_when_files_over=30,
587 collapse_when_files_over=30,
588 disable_new_comments=not c.allowed_to_comment,
588 disable_new_comments=not c.allowed_to_comment,
589 deleted_files_comments=c.deleted_files_comments,
589 deleted_files_comments=c.deleted_files_comments,
590 inline_comments=c.inline_comments)}
590 inline_comments=c.inline_comments)}
591 % endif
591 % endif
592
592
593 </div>
593 </div>
594 % else:
594 % else:
595 ## skipping commits we need to clear the view for missing commits
595 ## skipping commits we need to clear the view for missing commits
596 <div style="clear:both;"></div>
596 <div style="clear:both;"></div>
597 % endif
597 % endif
598
598
599 </div>
599 </div>
600 </div>
600 </div>
601
601
602 ## template for inline comment form
602 ## template for inline comment form
603 <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
603 <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
604
604
605 ## render general comments
605 ## render general comments
606
606
607 <div id="comment-tr-show">
607 <div id="comment-tr-show">
608 <div class="comment">
608 <div class="comment">
609 % if general_outdated_comm_count_ver:
609 % if general_outdated_comm_count_ver:
610 <div class="meta">
610 <div class="meta">
611 % if general_outdated_comm_count_ver == 1:
611 % if general_outdated_comm_count_ver == 1:
612 ${_('there is {num} general comment from older versions').format(num=general_outdated_comm_count_ver)},
612 ${_('there is {num} general comment from older versions').format(num=general_outdated_comm_count_ver)},
613 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show it')}</a>
613 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show it')}</a>
614 % else:
614 % else:
615 ${_('there are {num} general comments from older versions').format(num=general_outdated_comm_count_ver)},
615 ${_('there are {num} general comments from older versions').format(num=general_outdated_comm_count_ver)},
616 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show them')}</a>
616 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show them')}</a>
617 % endif
617 % endif
618 </div>
618 </div>
619 % endif
619 % endif
620 </div>
620 </div>
621 </div>
621 </div>
622
622
623 ${comment.generate_comments(c.comments, include_pull_request=True, is_pull_request=True)}
623 ${comment.generate_comments(c.comments, include_pull_request=True, is_pull_request=True)}
624
624
625 % if not c.pull_request.is_closed():
625 % if not c.pull_request.is_closed():
626 ## merge status, and merge action
626 ## merge status, and merge action
627 <div class="pull-request-merge">
627 <div class="pull-request-merge">
628 <%include file="/pullrequests/pullrequest_merge_checks.mako"/>
628 <%include file="/pullrequests/pullrequest_merge_checks.mako"/>
629 </div>
629 </div>
630
630
631 ## main comment form and it status
631 ## main comment form and it status
632 ${comment.comments(h.route_path('pullrequest_comment_create', repo_name=c.repo_name,
632 ${comment.comments(h.route_path('pullrequest_comment_create', repo_name=c.repo_name,
633 pull_request_id=c.pull_request.pull_request_id),
633 pull_request_id=c.pull_request.pull_request_id),
634 c.pull_request_review_status,
634 c.pull_request_review_status,
635 is_pull_request=True, change_status=c.allowed_to_change_status)}
635 is_pull_request=True, change_status=c.allowed_to_change_status)}
636 %endif
636 %endif
637
637
638 <script type="text/javascript">
638 <script type="text/javascript">
639 if (location.hash) {
639 if (location.hash) {
640 var result = splitDelimitedHash(location.hash);
640 var result = splitDelimitedHash(location.hash);
641 var line = $('html').find(result.loc);
641 var line = $('html').find(result.loc);
642 // show hidden comments if we use location.hash
642 // show hidden comments if we use location.hash
643 if (line.hasClass('comment-general')) {
643 if (line.hasClass('comment-general')) {
644 $(line).show();
644 $(line).show();
645 } else if (line.hasClass('comment-inline')) {
645 } else if (line.hasClass('comment-inline')) {
646 $(line).show();
646 $(line).show();
647 var $cb = $(line).closest('.cb');
647 var $cb = $(line).closest('.cb');
648 $cb.removeClass('cb-collapsed')
648 $cb.removeClass('cb-collapsed')
649 }
649 }
650 if (line.length > 0){
650 if (line.length > 0){
651 offsetScroll(line, 70);
651 offsetScroll(line, 70);
652 }
652 }
653 }
653 }
654
654
655 versionController = new VersionController();
655 versionController = new VersionController();
656 versionController.init();
656 versionController.init();
657
657
658 reviewersController = new ReviewersController();
658 reviewersController = new ReviewersController();
659
659
660 $(function(){
660 $(function(){
661
661
662 // custom code mirror
662 // custom code mirror
663 var codeMirrorInstance = $('#pr-description-input').get(0).MarkupForm.cm;
663 var codeMirrorInstance = $('#pr-description-input').get(0).MarkupForm.cm;
664
664
665 var PRDetails = {
665 var PRDetails = {
666 editButton: $('#open_edit_pullrequest'),
666 editButton: $('#open_edit_pullrequest'),
667 closeButton: $('#close_edit_pullrequest'),
667 closeButton: $('#close_edit_pullrequest'),
668 deleteButton: $('#delete_pullrequest'),
668 deleteButton: $('#delete_pullrequest'),
669 viewFields: $('#pr-desc, #pr-title'),
669 viewFields: $('#pr-desc, #pr-title'),
670 editFields: $('#pr-desc-edit, #pr-title-edit, #pr-save'),
670 editFields: $('#pr-desc-edit, #pr-title-edit, #pr-save'),
671
671
672 init: function() {
672 init: function() {
673 var that = this;
673 var that = this;
674 this.editButton.on('click', function(e) { that.edit(); });
674 this.editButton.on('click', function(e) { that.edit(); });
675 this.closeButton.on('click', function(e) { that.view(); });
675 this.closeButton.on('click', function(e) { that.view(); });
676 },
676 },
677
677
678 edit: function(event) {
678 edit: function(event) {
679 this.viewFields.hide();
679 this.viewFields.hide();
680 this.editButton.hide();
680 this.editButton.hide();
681 this.deleteButton.hide();
681 this.deleteButton.hide();
682 this.closeButton.show();
682 this.closeButton.show();
683 this.editFields.show();
683 this.editFields.show();
684 codeMirrorInstance.refresh();
684 codeMirrorInstance.refresh();
685 },
685 },
686
686
687 view: function(event) {
687 view: function(event) {
688 this.editButton.show();
688 this.editButton.show();
689 this.deleteButton.show();
689 this.deleteButton.show();
690 this.editFields.hide();
690 this.editFields.hide();
691 this.closeButton.hide();
691 this.closeButton.hide();
692 this.viewFields.show();
692 this.viewFields.show();
693 }
693 }
694 };
694 };
695
695
696 var ReviewersPanel = {
696 var ReviewersPanel = {
697 editButton: $('#open_edit_reviewers'),
697 editButton: $('#open_edit_reviewers'),
698 closeButton: $('#close_edit_reviewers'),
698 closeButton: $('#close_edit_reviewers'),
699 addButton: $('#add_reviewer'),
699 addButton: $('#add_reviewer'),
700 removeButtons: $('.reviewer_member_remove,.reviewer_member_mandatory_remove'),
700 removeButtons: $('.reviewer_member_remove,.reviewer_member_mandatory_remove'),
701
701
702 init: function() {
702 init: function() {
703 var self = this;
703 var self = this;
704 this.editButton.on('click', function(e) { self.edit(); });
704 this.editButton.on('click', function(e) { self.edit(); });
705 this.closeButton.on('click', function(e) { self.close(); });
705 this.closeButton.on('click', function(e) { self.close(); });
706 },
706 },
707
707
708 edit: function(event) {
708 edit: function(event) {
709 this.editButton.hide();
709 this.editButton.hide();
710 this.closeButton.show();
710 this.closeButton.show();
711 this.addButton.show();
711 this.addButton.show();
712 this.removeButtons.css('visibility', 'visible');
712 this.removeButtons.css('visibility', 'visible');
713 // review rules
713 // review rules
714 reviewersController.loadReviewRules(
714 reviewersController.loadReviewRules(
715 ${c.pull_request.reviewer_data_json | n});
715 ${c.pull_request.reviewer_data_json | n});
716 },
716 },
717
717
718 close: function(event) {
718 close: function(event) {
719 this.editButton.show();
719 this.editButton.show();
720 this.closeButton.hide();
720 this.closeButton.hide();
721 this.addButton.hide();
721 this.addButton.hide();
722 this.removeButtons.css('visibility', 'hidden');
722 this.removeButtons.css('visibility', 'hidden');
723 // hide review rules
723 // hide review rules
724 reviewersController.hideReviewRules()
724 reviewersController.hideReviewRules()
725 }
725 }
726 };
726 };
727
727
728 PRDetails.init();
728 PRDetails.init();
729 ReviewersPanel.init();
729 ReviewersPanel.init();
730
730
731 showOutdated = function(self){
731 showOutdated = function(self){
732 $('.comment-inline.comment-outdated').show();
732 $('.comment-inline.comment-outdated').show();
733 $('.filediff-outdated').show();
733 $('.filediff-outdated').show();
734 $('.showOutdatedComments').hide();
734 $('.showOutdatedComments').hide();
735 $('.hideOutdatedComments').show();
735 $('.hideOutdatedComments').show();
736 };
736 };
737
737
738 hideOutdated = function(self){
738 hideOutdated = function(self){
739 $('.comment-inline.comment-outdated').hide();
739 $('.comment-inline.comment-outdated').hide();
740 $('.filediff-outdated').hide();
740 $('.filediff-outdated').hide();
741 $('.hideOutdatedComments').hide();
741 $('.hideOutdatedComments').hide();
742 $('.showOutdatedComments').show();
742 $('.showOutdatedComments').show();
743 };
743 };
744
744
745 refreshMergeChecks = function(){
745 refreshMergeChecks = function(){
746 var loadUrl = "${request.current_route_path(_query=dict(merge_checks=1))}";
746 var loadUrl = "${request.current_route_path(_query=dict(merge_checks=1))}";
747 $('.pull-request-merge').css('opacity', 0.3);
747 $('.pull-request-merge').css('opacity', 0.3);
748 $('.action-buttons-extra').css('opacity', 0.3);
748 $('.action-buttons-extra').css('opacity', 0.3);
749
749
750 $('.pull-request-merge').load(
750 $('.pull-request-merge').load(
751 loadUrl, function() {
751 loadUrl, function() {
752 $('.pull-request-merge').css('opacity', 1);
752 $('.pull-request-merge').css('opacity', 1);
753
753
754 $('.action-buttons-extra').css('opacity', 1);
754 $('.action-buttons-extra').css('opacity', 1);
755 injectCloseAction();
755 injectCloseAction();
756 }
756 }
757 );
757 );
758 };
758 };
759
759
760 injectCloseAction = function() {
760 injectCloseAction = function() {
761 var closeAction = $('#close-pull-request-action').html();
761 var closeAction = $('#close-pull-request-action').html();
762 var $actionButtons = $('.action-buttons-extra');
762 var $actionButtons = $('.action-buttons-extra');
763 // clear the action before
763 // clear the action before
764 $actionButtons.html("");
764 $actionButtons.html("");
765 $actionButtons.html(closeAction);
765 $actionButtons.html(closeAction);
766 };
766 };
767
767
768 closePullRequest = function (status) {
768 closePullRequest = function (status) {
769 // inject closing flag
769 // inject closing flag
770 $('.action-buttons-extra').append('<input type="hidden" class="close-pr-input" id="close_pull_request" value="1">');
770 $('.action-buttons-extra').append('<input type="hidden" class="close-pr-input" id="close_pull_request" value="1">');
771 $(generalCommentForm.statusChange).select2("val", status).trigger('change');
771 $(generalCommentForm.statusChange).select2("val", status).trigger('change');
772 $(generalCommentForm.submitForm).submit();
772 $(generalCommentForm.submitForm).submit();
773 };
773 };
774
774
775 $('#show-outdated-comments').on('click', function(e){
775 $('#show-outdated-comments').on('click', function(e){
776 var button = $(this);
776 var button = $(this);
777 var outdated = $('.comment-outdated');
777 var outdated = $('.comment-outdated');
778
778
779 if (button.html() === "(Show)") {
779 if (button.html() === "(Show)") {
780 button.html("(Hide)");
780 button.html("(Hide)");
781 outdated.show();
781 outdated.show();
782 } else {
782 } else {
783 button.html("(Show)");
783 button.html("(Show)");
784 outdated.hide();
784 outdated.hide();
785 }
785 }
786 });
786 });
787
787
788 $('.show-inline-comments').on('change', function(e){
788 $('.show-inline-comments').on('change', function(e){
789 var show = 'none';
789 var show = 'none';
790 var target = e.currentTarget;
790 var target = e.currentTarget;
791 if(target.checked){
791 if(target.checked){
792 show = ''
792 show = ''
793 }
793 }
794 var boxid = $(target).attr('id_for');
794 var boxid = $(target).attr('id_for');
795 var comments = $('#{0} .inline-comments'.format(boxid));
795 var comments = $('#{0} .inline-comments'.format(boxid));
796 var fn_display = function(idx){
796 var fn_display = function(idx){
797 $(this).css('display', show);
797 $(this).css('display', show);
798 };
798 };
799 $(comments).each(fn_display);
799 $(comments).each(fn_display);
800 var btns = $('#{0} .inline-comments-button'.format(boxid));
800 var btns = $('#{0} .inline-comments-button'.format(boxid));
801 $(btns).each(fn_display);
801 $(btns).each(fn_display);
802 });
802 });
803
803
804 $('#merge_pull_request_form').submit(function() {
804 $('#merge_pull_request_form').submit(function() {
805 if (!$('#merge_pull_request').attr('disabled')) {
805 if (!$('#merge_pull_request').attr('disabled')) {
806 $('#merge_pull_request').attr('disabled', 'disabled');
806 $('#merge_pull_request').attr('disabled', 'disabled');
807 }
807 }
808 return true;
808 return true;
809 });
809 });
810
810
811 $('#edit_pull_request').on('click', function(e){
811 $('#edit_pull_request').on('click', function(e){
812 var title = $('#pr-title-input').val();
812 var title = $('#pr-title-input').val();
813 var description = codeMirrorInstance.getValue();
813 var description = codeMirrorInstance.getValue();
814 var renderer = $('#pr-renderer-input').val();
814 var renderer = $('#pr-renderer-input').val();
815 editPullRequest(
815 editPullRequest(
816 "${c.repo_name}", "${c.pull_request.pull_request_id}",
816 "${c.repo_name}", "${c.pull_request.pull_request_id}",
817 title, description, renderer);
817 title, description, renderer);
818 });
818 });
819
819
820 $('#update_pull_request').on('click', function(e){
820 $('#update_pull_request').on('click', function(e){
821 $(this).attr('disabled', 'disabled');
821 $(this).attr('disabled', 'disabled');
822 $(this).addClass('disabled');
822 $(this).addClass('disabled');
823 $(this).html(_gettext('Saving...'));
823 $(this).html(_gettext('Saving...'));
824 reviewersController.updateReviewers(
824 reviewersController.updateReviewers(
825 "${c.repo_name}", "${c.pull_request.pull_request_id}");
825 "${c.repo_name}", "${c.pull_request.pull_request_id}");
826 });
826 });
827
827
828 $('#update_commits').on('click', function(e){
828 $('#update_commits').on('click', function(e){
829 var isDisabled = !$(e.currentTarget).attr('disabled');
829 var isDisabled = !$(e.currentTarget).attr('disabled');
830 $(e.currentTarget).attr('disabled', 'disabled');
830 $(e.currentTarget).attr('disabled', 'disabled');
831 $(e.currentTarget).addClass('disabled');
831 $(e.currentTarget).addClass('disabled');
832 $(e.currentTarget).removeClass('btn-primary');
832 $(e.currentTarget).removeClass('btn-primary');
833 $(e.currentTarget).text(_gettext('Updating...'));
833 $(e.currentTarget).text(_gettext('Updating...'));
834 if(isDisabled){
834 if(isDisabled){
835 updateCommits(
835 updateCommits(
836 "${c.repo_name}", "${c.pull_request.pull_request_id}");
836 "${c.repo_name}", "${c.pull_request.pull_request_id}");
837 }
837 }
838 });
838 });
839 // fixing issue with caches on firefox
839 // fixing issue with caches on firefox
840 $('#update_commits').removeAttr("disabled");
840 $('#update_commits').removeAttr("disabled");
841
841
842 $('.show-inline-comments').on('click', function(e){
842 $('.show-inline-comments').on('click', function(e){
843 var boxid = $(this).attr('data-comment-id');
843 var boxid = $(this).attr('data-comment-id');
844 var button = $(this);
844 var button = $(this);
845
845
846 if(button.hasClass("comments-visible")) {
846 if(button.hasClass("comments-visible")) {
847 $('#{0} .inline-comments'.format(boxid)).each(function(index){
847 $('#{0} .inline-comments'.format(boxid)).each(function(index){
848 $(this).hide();
848 $(this).hide();
849 });
849 });
850 button.removeClass("comments-visible");
850 button.removeClass("comments-visible");
851 } else {
851 } else {
852 $('#{0} .inline-comments'.format(boxid)).each(function(index){
852 $('#{0} .inline-comments'.format(boxid)).each(function(index){
853 $(this).show();
853 $(this).show();
854 });
854 });
855 button.addClass("comments-visible");
855 button.addClass("comments-visible");
856 }
856 }
857 });
857 });
858
858
859 // register submit callback on commentForm form to track TODOs
859 // register submit callback on commentForm form to track TODOs
860 window.commentFormGlobalSubmitSuccessCallback = function(){
860 window.commentFormGlobalSubmitSuccessCallback = function(){
861 refreshMergeChecks();
861 refreshMergeChecks();
862 };
862 };
863 // initial injection
863 // initial injection
864 injectCloseAction();
864 injectCloseAction();
865
865
866 ReviewerAutoComplete('#user');
866 ReviewerAutoComplete('#user');
867
867
868 })
868 })
869 </script>
869 </script>
870
870
871 </div>
871 </div>
872 </div>
872 </div>
873
873
874 </%def>
874 </%def>
@@ -1,108 +1,107 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.mako"/>
2 <%inherit file="/base/base.mako"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 %if c.repo_name:
5 %if c.repo_name:
6 ${_('Search inside repository %(repo_name)s') % {'repo_name': c.repo_name}}
6 ${_('Search inside repository %(repo_name)s') % {'repo_name': c.repo_name}}
7 %else:
7 %else:
8 ${_('Search inside all accessible repositories')}
8 ${_('Search inside all accessible repositories')}
9 %endif
9 %endif
10 %if c.rhodecode_name:
10 %if c.rhodecode_name:
11 &middot; ${h.branding(c.rhodecode_name)}
11 &middot; ${h.branding(c.rhodecode_name)}
12 %endif
12 %endif
13 </%def>
13 </%def>
14
14
15 <%def name="breadcrumbs_links()">
15 <%def name="breadcrumbs_links()">
16 %if c.repo_name:
16 %if c.repo_name:
17 ${_('Search inside repository %(repo_name)s') % {'repo_name': c.repo_name}}
17 ${_('Search inside repository %(repo_name)s') % {'repo_name': c.repo_name}}
18 %else:
18 %else:
19 ${_('Search inside all accessible repositories')}
19 ${_('Search inside all accessible repositories')}
20 %endif
20 %endif
21 %if c.cur_query:
21 %if c.cur_query:
22 &raquo;
22 &raquo;
23 ${c.cur_query}
23 ${c.cur_query}
24 %endif
24 %endif
25 </%def>
25 </%def>
26
26
27 <%def name="menu_bar_nav()">
27 <%def name="menu_bar_nav()">
28 %if c.repo_name:
28 %if c.repo_name:
29 ${self.menu_items(active='repositories')}
29 ${self.menu_items(active='repositories')}
30 %else:
30 %else:
31 ${self.menu_items(active='search')}
31 ${self.menu_items(active='search')}
32 %endif
32 %endif
33 </%def>
33 </%def>
34
34
35 <%def name="menu_bar_subnav()">
35 <%def name="menu_bar_subnav()">
36 %if c.repo_name:
36 %if c.repo_name:
37 ${self.repo_menu(active='options')}
37 ${self.repo_menu(active='options')}
38 %endif
38 %endif
39 </%def>
39 </%def>
40
40
41 <%def name="main()">
41 <%def name="main()">
42 <div class="box">
42 <div class="box">
43 %if c.repo_name:
43 %if c.repo_name:
44 <!-- box / title -->
44 <!-- box / title -->
45 <div class="title">
45 <div class="title">
46 ${self.repo_page_title(c.rhodecode_db_repo)}
46 ${self.repo_page_title(c.rhodecode_db_repo)}
47 </div>
47 </div>
48 ${h.form(h.route_path('search_repo',repo_name=c.repo_name),method='get')}
48 ${h.form(h.route_path('search_repo',repo_name=c.repo_name),method='get')}
49 %else:
49 %else:
50 <!-- box / title -->
50 <!-- box / title -->
51 <div class="title">
51 <div class="title">
52 ${self.breadcrumbs()}
52 ${self.breadcrumbs()}
53 <ul class="links">&nbsp;</ul>
53 <ul class="links">&nbsp;</ul>
54 </div>
54 </div>
55 <!-- end box / title -->
55 <!-- end box / title -->
56 ${h.form(h.route_path('search'), method='get')}
56 ${h.form(h.route_path('search'), method='get')}
57 %endif
57 %endif
58 <div class="form search-form">
58 <div class="form search-form">
59 <div class="fields">
59 <div class="fields">
60 <label for="q">${_('Search item')}:</label>
60 ${h.text('q', c.cur_query, placeholder="Enter query...")}
61 ${h.text('q', c.cur_query)}
62
61
63 ${h.select('type',c.search_type,[('content',_('File contents')), ('commit',_('Commit messages')), ('path',_('File names')),],id='id_search_type')}
62 ${h.select('type',c.search_type,[('content',_('File contents')), ('commit',_('Commit messages')), ('path',_('File names')),],id='id_search_type')}
64 <input type="submit" value="${_('Search')}" class="btn"/>
63 <input type="submit" value="${_('Search')}" class="btn"/>
65 <br/>
64 <br/>
66
65
67 <div class="search-feedback-items">
66 <div class="search-feedback-items">
68 % for error in c.errors:
67 % for error in c.errors:
69 <span class="error-message">
68 <span class="error-message">
70 % for k,v in error.asdict().items():
69 % for k,v in error.asdict().items():
71 ${k} - ${v}
70 ${k} - ${v}
72 % endfor
71 % endfor
73 </span>
72 </span>
74 % endfor
73 % endfor
75 <div class="field">
74 <div class="field">
76 <p class="filterexample" style="position: inherit" onclick="$('#search-help').toggle()">${_('Example Queries')}</p>
75 <p class="filterexample" style="position: inherit" onclick="$('#search-help').toggle()">${_('Example Queries')}</p>
77 <pre id="search-help" style="display: none">${h.tooltip(h.search_filter_help(c.searcher, request))}</pre>
76 <pre id="search-help" style="display: none">${h.tooltip(h.search_filter_help(c.searcher, request))}</pre>
78 </div>
77 </div>
79
78
80 <div class="field">${c.runtime}</div>
79 <div class="field">${c.runtime}</div>
81 </div>
80 </div>
82 </div>
81 </div>
83 </div>
82 </div>
84
83
85 ${h.end_form()}
84 ${h.end_form()}
86 <div class="search">
85 <div class="search">
87 % if c.search_type == 'content':
86 % if c.search_type == 'content':
88 <%include file='search_content.mako'/>
87 <%include file='search_content.mako'/>
89 % elif c.search_type == 'path':
88 % elif c.search_type == 'path':
90 <%include file='search_path.mako'/>
89 <%include file='search_path.mako'/>
91 % elif c.search_type == 'commit':
90 % elif c.search_type == 'commit':
92 <%include file='search_commit.mako'/>
91 <%include file='search_commit.mako'/>
93 % elif c.search_type == 'repository':
92 % elif c.search_type == 'repository':
94 <%include file='search_repository.mako'/>
93 <%include file='search_repository.mako'/>
95 % endif
94 % endif
96 </div>
95 </div>
97 </div>
96 </div>
98 <script>
97 <script>
99 $(document).ready(function(){
98 $(document).ready(function(){
100 $("#id_search_type").select2({
99 $("#id_search_type").select2({
101 'containerCssClass': "drop-menu",
100 'containerCssClass': "drop-menu",
102 'dropdownCssClass': "drop-menu-dropdown",
101 'dropdownCssClass': "drop-menu-dropdown",
103 'dropdownAutoWidth': true,
102 'dropdownAutoWidth': true,
104 'minimumResultsForSearch': -1
103 'minimumResultsForSearch': -1
105 });
104 });
106 })
105 })
107 </script>
106 </script>
108 </%def>
107 </%def>
@@ -1,82 +1,82 b''
1 <%namespace name="base" file="/base/base.mako"/>
1 <%namespace name="base" file="/base/base.mako"/>
2
2
3 <table class="rctable search-results">
3 <table class="rctable search-results">
4 <tr>
4 <tr>
5 <th>${_('Repository')}</th>
5 <th>${_('Repository')}</th>
6 <th>${_('Commit')}</th>
6 <th>${_('Commit')}</th>
7 <th></th>
7 <th></th>
8 <th>${_('Commit message')}</th>
8 <th>${_('Commit message')}</th>
9 <th>
9 <th>
10 %if c.sort == 'newfirst':
10 %if c.sort == 'newfirst':
11 <a href="${c.url_generator(sort='oldfirst')}">${_('Age (new first)')}</a>
11 <a href="${c.url_generator(sort='oldfirst')}">${_('Age (new first)')}</a>
12 %else:
12 %else:
13 <a href="${c.url_generator(sort='newfirst')}">${_('Age (old first)')}</a>
13 <a href="${c.url_generator(sort='newfirst')}">${_('Age (old first)')}</a>
14 %endif
14 %endif
15 </th>
15 </th>
16 <th>${_('Author')}</th>
16 <th>${_('Author')}</th>
17 </tr>
17 </tr>
18 %for entry in c.formatted_results:
18 %for entry in c.formatted_results:
19 ## search results are additionally filtered, and this check is just a safe gate
19 ## search results are additionally filtered, and this check is just a safe gate
20 % if h.HasRepoPermissionAny('repository.write','repository.read','repository.admin')(entry['repository'], 'search results commit check'):
20 % if h.HasRepoPermissionAny('repository.write','repository.read','repository.admin')(entry['repository'], 'search results commit check'):
21 <tr class="body">
21 <tr class="body">
22 <td class="td-componentname">
22 <td class="td-componentname">
23 %if h.get_repo_type_by_name(entry.get('repository')) == 'hg':
23 %if h.get_repo_type_by_name(entry.get('repository')) == 'hg':
24 <i class="icon-hg"></i>
24 <i class="icon-hg"></i>
25 %elif h.get_repo_type_by_name(entry.get('repository')) == 'git':
25 %elif h.get_repo_type_by_name(entry.get('repository')) == 'git':
26 <i class="icon-git"></i>
26 <i class="icon-git"></i>
27 %elif h.get_repo_type_by_name(entry.get('repository')) == 'svn':
27 %elif h.get_repo_type_by_name(entry.get('repository')) == 'svn':
28 <i class="icon-svn"></i>
28 <i class="icon-svn"></i>
29 %endif
29 %endif
30 ${h.link_to(entry['repository'], h.route_path('repo_summary',repo_name=entry['repository']))}
30 ${h.link_to(entry['repository'], h.route_path('repo_summary',repo_name=entry['repository']))}
31 </td>
31 </td>
32 <td class="td-commit">
32 <td class="td-commit">
33 ${h.link_to(h._shorten_commit_id(entry['commit_id']),
33 ${h.link_to(h._shorten_commit_id(entry['commit_id']),
34 h.route_path('repo_commit',repo_name=entry['repository'],commit_id=entry['commit_id']))}
34 h.route_path('repo_commit',repo_name=entry['repository'],commit_id=entry['commit_id']))}
35 </td>
35 </td>
36 <td class="td-message expand_commit search open" data-commit-id="${h.md5_safe(entry['repository'])+entry['commit_id']}" id="t-${h.md5_safe(entry['repository'])+entry['commit_id']}" title="${_('Expand commit message')}">
36 <td class="td-message expand_commit search open" data-commit-id="${h.md5_safe(entry['repository'])+entry['commit_id']}" id="t-${h.md5_safe(entry['repository'])+entry['commit_id']}" title="${_('Expand commit message')}">
37 <div class="show_more_col">
37 <div class="show_more_col">
38 <i class="show_more"></i>&nbsp;
38 <i class="icon-more-linked"></i>&nbsp;
39 </div>
39 </div>
40 </td>
40 </td>
41 <td data-commit-id="${h.md5_safe(entry['repository'])+entry['commit_id']}" id="c-${h.md5_safe(entry['repository'])+entry['commit_id']}" class="message td-description open">
41 <td data-commit-id="${h.md5_safe(entry['repository'])+entry['commit_id']}" id="c-${h.md5_safe(entry['repository'])+entry['commit_id']}" class="message td-description open">
42 %if entry.get('message_hl'):
42 %if entry.get('message_hl'):
43 ${h.literal(entry['message_hl'])}
43 ${h.literal(entry['message_hl'])}
44 %else:
44 %else:
45 ${h.urlify_commit_message(entry['message'], entry['repository'])}
45 ${h.urlify_commit_message(entry['message'], entry['repository'])}
46 %endif
46 %endif
47 </td>
47 </td>
48 <td class="td-time">
48 <td class="td-time">
49 ${h.age_component(h.time_to_utcdatetime(entry['date']))}
49 ${h.age_component(h.time_to_utcdatetime(entry['date']))}
50 </td>
50 </td>
51
51
52 <td class="td-user author">
52 <td class="td-user author">
53 ${base.gravatar_with_user(entry['author'])}
53 ${base.gravatar_with_user(entry['author'])}
54 </td>
54 </td>
55 </tr>
55 </tr>
56 % endif
56 % endif
57 %endfor
57 %endfor
58 </table>
58 </table>
59
59
60 %if c.cur_query and c.formatted_results:
60 %if c.cur_query and c.formatted_results:
61 <div class="pagination-wh pagination-left">
61 <div class="pagination-wh pagination-left">
62 ${c.formatted_results.pager('$link_previous ~2~ $link_next')}
62 ${c.formatted_results.pager('$link_previous ~2~ $link_next')}
63 </div>
63 </div>
64 %endif
64 %endif
65
65
66 <script>
66 <script>
67 $('.expand_commit').on('click',function(e){
67 $('.expand_commit').on('click',function(e){
68 var target_expand = $(this);
68 var target_expand = $(this);
69 var cid = target_expand.data('commit-id');
69 var cid = target_expand.data('commit-id');
70
70
71 if (target_expand.hasClass('open')){
71 if (target_expand.hasClass('open')){
72 $('#c-'+cid).css({'height': '1.5em', 'white-space': 'nowrap', 'text-overflow': 'ellipsis', 'overflow':'hidden'})
72 $('#c-'+cid).css({'height': '1.5em', 'white-space': 'nowrap', 'text-overflow': 'ellipsis', 'overflow':'hidden'})
73 $('#t-'+cid).css({'height': 'auto', 'line-height': '.9em', 'text-overflow': 'ellipsis', 'overflow':'hidden'})
73 $('#t-'+cid).css({'height': 'auto', 'line-height': '.9em', 'text-overflow': 'ellipsis', 'overflow':'hidden'})
74 target_expand.removeClass('open');
74 target_expand.removeClass('open');
75 }
75 }
76 else {
76 else {
77 $('#c-'+cid).css({'height': 'auto', 'white-space': 'normal', 'text-overflow': 'initial', 'overflow':'visible'})
77 $('#c-'+cid).css({'height': 'auto', 'white-space': 'normal', 'text-overflow': 'initial', 'overflow':'visible'})
78 $('#t-'+cid).css({'height': 'auto', 'max-height': 'none', 'text-overflow': 'initial', 'overflow':'visible'})
78 $('#t-'+cid).css({'height': 'auto', 'max-height': 'none', 'text-overflow': 'initial', 'overflow':'visible'})
79 target_expand.addClass('open');
79 target_expand.addClass('open');
80 }
80 }
81 });
81 });
82 </script>
82 </script>
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
General Comments 0
You need to be logged in to leave comments. Login now