##// 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 1 # top level files
2 2
3 3 include MANIFEST.in
4 4 include README.rst
5 5 include CHANGES.rst
6 6 include LICENSE.txt
7 7
8 8 include rhodecode/VERSION
9 9
10 10 # docs
11 11 recursive-include docs *
12 12
13 13 # all config files
14 14 recursive-include configs *
15 15
16 16 # translations
17 17 recursive-include rhodecode/i18n *
18 18
19 19 # non-python core stuff
20 20 recursive-include rhodecode *.cfg
21 21 recursive-include rhodecode *.json
22 22 recursive-include rhodecode *.ini_tmpl
23 23 recursive-include rhodecode *.sh
24 24 recursive-include rhodecode *.mako
25 25
26 26 # 502 page
27 27 include rhodecode/public/502.html
28 28
29 29 # robots
30 30 include rhodecode/public/robots.txt
31 31
32 32 # images, css
33 33 include rhodecode/public/css/*.css
34 34 include rhodecode/public/images/*.*
35 35 include rhodecode/public/images/ee_features/*.*
36 36
37 37 # sound files
38 38 include rhodecode/public/sounds/*.mp3
39 39 include rhodecode/public/sounds/*.wav
40 40
41 41 # fonts
42 recursive-include rhodecode/public/fonts/ProximaNova *
43 42 recursive-include rhodecode/public/fonts/RCIcons *
44 43
45 44 # js
46 45 recursive-include rhodecode/public/js *
47 46
48 47 # templates
49 48 recursive-include rhodecode/templates *
50 49
51 50 # skip any tests files
52 51 recursive-exclude rhodecode/tests *
53 52
@@ -1,13 +1,13 b''
1 1 .menuselection, .guilabel {
2 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 4 font-style: oblique;
5 5 }
6 6
7 .version{
7 .version {
8 8 display: none;
9 }
9 }
10 10
11 .pre{
12 color:#000
13 }
11 .pre {
12 color: #000
13 }
@@ -1,2105 +1,2108 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2018 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 """
22 22 Helper functions
23 23
24 24 Consists of functions to typically be used within templates, but also
25 25 available to Controllers. This module is available to both as 'h'.
26 26 """
27 27
28 28 import os
29 29 import random
30 30 import hashlib
31 31 import StringIO
32 32 import textwrap
33 33 import urllib
34 34 import math
35 35 import logging
36 36 import re
37 37 import urlparse
38 38 import time
39 39 import string
40 40 import hashlib
41 41 from collections import OrderedDict
42 42
43 43 import pygments
44 44 import itertools
45 45 import fnmatch
46 46 import bleach
47 47
48 48 from datetime import datetime
49 49 from functools import partial
50 50 from pygments.formatters.html import HtmlFormatter
51 51 from pygments import highlight as code_highlight
52 52 from pygments.lexers import (
53 53 get_lexer_by_name, get_lexer_for_filename, get_lexer_for_mimetype)
54 54
55 55 from pyramid.threadlocal import get_current_request
56 56
57 57 from webhelpers.html import literal, HTML, escape
58 58 from webhelpers.html.tools import *
59 59 from webhelpers.html.builder import make_tag
60 60 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
61 61 end_form, file, form as wh_form, hidden, image, javascript_link, link_to, \
62 62 link_to_if, link_to_unless, ol, required_legend, select, stylesheet_link, \
63 63 submit, text, password, textarea, title, ul, xml_declaration, radio
64 64 from webhelpers.html.tools import auto_link, button_to, highlight, \
65 65 js_obfuscate, mail_to, strip_links, strip_tags, tag_re
66 66 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
67 67 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
68 68 replace_whitespace, urlify, truncate, wrap_paragraphs
69 69 from webhelpers.date import time_ago_in_words
70 70 from webhelpers.paginate import Page as _Page
71 71 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
72 72 convert_boolean_attrs, NotGiven, _make_safe_id_component
73 73 from webhelpers2.number import format_byte_size
74 74
75 75 from rhodecode.lib.action_parser import action_parser
76 76 from rhodecode.lib.ext_json import json
77 77 from rhodecode.lib.utils import repo_name_slug, get_custom_lexer
78 78 from rhodecode.lib.utils2 import str2bool, safe_unicode, safe_str, \
79 79 get_commit_safe, datetime_to_time, time_to_datetime, time_to_utcdatetime, \
80 80 AttributeDict, safe_int, md5, md5_safe
81 81 from rhodecode.lib.markup_renderer import MarkupRenderer, relative_links
82 82 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
83 83 from rhodecode.lib.vcs.backends.base import BaseChangeset, EmptyCommit
84 84 from rhodecode.config.conf import DATE_FORMAT, DATETIME_FORMAT
85 85 from rhodecode.model.changeset_status import ChangesetStatusModel
86 86 from rhodecode.model.db import Permission, User, Repository
87 87 from rhodecode.model.repo_group import RepoGroupModel
88 88 from rhodecode.model.settings import IssueTrackerSettingsModel
89 89
90 90 log = logging.getLogger(__name__)
91 91
92 92
93 93 DEFAULT_USER = User.DEFAULT_USER
94 94 DEFAULT_USER_EMAIL = User.DEFAULT_USER_EMAIL
95 95
96 96
97 97 def asset(path, ver=None, **kwargs):
98 98 """
99 99 Helper to generate a static asset file path for rhodecode assets
100 100
101 101 eg. h.asset('images/image.png', ver='3923')
102 102
103 103 :param path: path of asset
104 104 :param ver: optional version query param to append as ?ver=
105 105 """
106 106 request = get_current_request()
107 107 query = {}
108 108 query.update(kwargs)
109 109 if ver:
110 110 query = {'ver': ver}
111 111 return request.static_path(
112 112 'rhodecode:public/{}'.format(path), _query=query)
113 113
114 114
115 115 default_html_escape_table = {
116 116 ord('&'): u'&amp;',
117 117 ord('<'): u'&lt;',
118 118 ord('>'): u'&gt;',
119 119 ord('"'): u'&quot;',
120 120 ord("'"): u'&#39;',
121 121 }
122 122
123 123
124 124 def html_escape(text, html_escape_table=default_html_escape_table):
125 125 """Produce entities within text."""
126 126 return text.translate(html_escape_table)
127 127
128 128
129 129 def chop_at_smart(s, sub, inclusive=False, suffix_if_chopped=None):
130 130 """
131 131 Truncate string ``s`` at the first occurrence of ``sub``.
132 132
133 133 If ``inclusive`` is true, truncate just after ``sub`` rather than at it.
134 134 """
135 135 suffix_if_chopped = suffix_if_chopped or ''
136 136 pos = s.find(sub)
137 137 if pos == -1:
138 138 return s
139 139
140 140 if inclusive:
141 141 pos += len(sub)
142 142
143 143 chopped = s[:pos]
144 144 left = s[pos:].strip()
145 145
146 146 if left and suffix_if_chopped:
147 147 chopped += suffix_if_chopped
148 148
149 149 return chopped
150 150
151 151
152 152 def shorter(text, size=20):
153 153 postfix = '...'
154 154 if len(text) > size:
155 155 return text[:size - len(postfix)] + postfix
156 156 return text
157 157
158 158
159 159 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
160 160 """
161 161 Reset button
162 162 """
163 163 _set_input_attrs(attrs, type, name, value)
164 164 _set_id_attr(attrs, id, name)
165 165 convert_boolean_attrs(attrs, ["disabled"])
166 166 return HTML.input(**attrs)
167 167
168 168 reset = _reset
169 169 safeid = _make_safe_id_component
170 170
171 171
172 172 def branding(name, length=40):
173 173 return truncate(name, length, indicator="")
174 174
175 175
176 176 def FID(raw_id, path):
177 177 """
178 178 Creates a unique ID for filenode based on it's hash of path and commit
179 179 it's safe to use in urls
180 180
181 181 :param raw_id:
182 182 :param path:
183 183 """
184 184
185 185 return 'c-%s-%s' % (short_id(raw_id), md5_safe(path)[:12])
186 186
187 187
188 188 class _GetError(object):
189 189 """Get error from form_errors, and represent it as span wrapped error
190 190 message
191 191
192 192 :param field_name: field to fetch errors for
193 193 :param form_errors: form errors dict
194 194 """
195 195
196 196 def __call__(self, field_name, form_errors):
197 197 tmpl = """<span class="error_msg">%s</span>"""
198 198 if form_errors and field_name in form_errors:
199 199 return literal(tmpl % form_errors.get(field_name))
200 200
201 201 get_error = _GetError()
202 202
203 203
204 204 class _ToolTip(object):
205 205
206 206 def __call__(self, tooltip_title, trim_at=50):
207 207 """
208 208 Special function just to wrap our text into nice formatted
209 209 autowrapped text
210 210
211 211 :param tooltip_title:
212 212 """
213 213 tooltip_title = escape(tooltip_title)
214 214 tooltip_title = tooltip_title.replace('<', '&lt;').replace('>', '&gt;')
215 215 return tooltip_title
216 216 tooltip = _ToolTip()
217 217
218 218
219 219 def files_breadcrumbs(repo_name, commit_id, file_path):
220 220 if isinstance(file_path, str):
221 221 file_path = safe_unicode(file_path)
222 222
223 223 # TODO: johbo: Is this always a url like path, or is this operating
224 224 # system dependent?
225 225 path_segments = file_path.split('/')
226 226
227 227 repo_name_html = escape(repo_name)
228 228 if len(path_segments) == 1 and path_segments[0] == '':
229 229 url_segments = [repo_name_html]
230 230 else:
231 231 url_segments = [
232 232 link_to(
233 233 repo_name_html,
234 234 route_path(
235 235 'repo_files',
236 236 repo_name=repo_name,
237 237 commit_id=commit_id,
238 238 f_path=''),
239 239 class_='pjax-link')]
240 240
241 241 last_cnt = len(path_segments) - 1
242 242 for cnt, segment in enumerate(path_segments):
243 243 if not segment:
244 244 continue
245 245 segment_html = escape(segment)
246 246
247 247 if cnt != last_cnt:
248 248 url_segments.append(
249 249 link_to(
250 250 segment_html,
251 251 route_path(
252 252 'repo_files',
253 253 repo_name=repo_name,
254 254 commit_id=commit_id,
255 255 f_path='/'.join(path_segments[:cnt + 1])),
256 256 class_='pjax-link'))
257 257 else:
258 258 url_segments.append(segment_html)
259 259
260 260 return literal('/'.join(url_segments))
261 261
262 262
263 263 class CodeHtmlFormatter(HtmlFormatter):
264 264 """
265 265 My code Html Formatter for source codes
266 266 """
267 267
268 268 def wrap(self, source, outfile):
269 269 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
270 270
271 271 def _wrap_code(self, source):
272 272 for cnt, it in enumerate(source):
273 273 i, t = it
274 274 t = '<div id="L%s">%s</div>' % (cnt + 1, t)
275 275 yield i, t
276 276
277 277 def _wrap_tablelinenos(self, inner):
278 278 dummyoutfile = StringIO.StringIO()
279 279 lncount = 0
280 280 for t, line in inner:
281 281 if t:
282 282 lncount += 1
283 283 dummyoutfile.write(line)
284 284
285 285 fl = self.linenostart
286 286 mw = len(str(lncount + fl - 1))
287 287 sp = self.linenospecial
288 288 st = self.linenostep
289 289 la = self.lineanchors
290 290 aln = self.anchorlinenos
291 291 nocls = self.noclasses
292 292 if sp:
293 293 lines = []
294 294
295 295 for i in range(fl, fl + lncount):
296 296 if i % st == 0:
297 297 if i % sp == 0:
298 298 if aln:
299 299 lines.append('<a href="#%s%d" class="special">%*d</a>' %
300 300 (la, i, mw, i))
301 301 else:
302 302 lines.append('<span class="special">%*d</span>' % (mw, i))
303 303 else:
304 304 if aln:
305 305 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
306 306 else:
307 307 lines.append('%*d' % (mw, i))
308 308 else:
309 309 lines.append('')
310 310 ls = '\n'.join(lines)
311 311 else:
312 312 lines = []
313 313 for i in range(fl, fl + lncount):
314 314 if i % st == 0:
315 315 if aln:
316 316 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
317 317 else:
318 318 lines.append('%*d' % (mw, i))
319 319 else:
320 320 lines.append('')
321 321 ls = '\n'.join(lines)
322 322
323 323 # in case you wonder about the seemingly redundant <div> here: since the
324 324 # content in the other cell also is wrapped in a div, some browsers in
325 325 # some configurations seem to mess up the formatting...
326 326 if nocls:
327 327 yield 0, ('<table class="%stable">' % self.cssclass +
328 328 '<tr><td><div class="linenodiv" '
329 329 'style="background-color: #f0f0f0; padding-right: 10px">'
330 330 '<pre style="line-height: 125%">' +
331 331 ls + '</pre></div></td><td id="hlcode" class="code">')
332 332 else:
333 333 yield 0, ('<table class="%stable">' % self.cssclass +
334 334 '<tr><td class="linenos"><div class="linenodiv"><pre>' +
335 335 ls + '</pre></div></td><td id="hlcode" class="code">')
336 336 yield 0, dummyoutfile.getvalue()
337 337 yield 0, '</td></tr></table>'
338 338
339 339
340 340 class SearchContentCodeHtmlFormatter(CodeHtmlFormatter):
341 341 def __init__(self, **kw):
342 342 # only show these line numbers if set
343 343 self.only_lines = kw.pop('only_line_numbers', [])
344 344 self.query_terms = kw.pop('query_terms', [])
345 345 self.max_lines = kw.pop('max_lines', 5)
346 346 self.line_context = kw.pop('line_context', 3)
347 347 self.url = kw.pop('url', None)
348 348
349 349 super(CodeHtmlFormatter, self).__init__(**kw)
350 350
351 351 def _wrap_code(self, source):
352 352 for cnt, it in enumerate(source):
353 353 i, t = it
354 354 t = '<pre>%s</pre>' % t
355 355 yield i, t
356 356
357 357 def _wrap_tablelinenos(self, inner):
358 358 yield 0, '<table class="code-highlight %stable">' % self.cssclass
359 359
360 360 last_shown_line_number = 0
361 361 current_line_number = 1
362 362
363 363 for t, line in inner:
364 364 if not t:
365 365 yield t, line
366 366 continue
367 367
368 368 if current_line_number in self.only_lines:
369 369 if last_shown_line_number + 1 != current_line_number:
370 370 yield 0, '<tr>'
371 371 yield 0, '<td class="line">...</td>'
372 372 yield 0, '<td id="hlcode" class="code"></td>'
373 373 yield 0, '</tr>'
374 374
375 375 yield 0, '<tr>'
376 376 if self.url:
377 377 yield 0, '<td class="line"><a href="%s#L%i">%i</a></td>' % (
378 378 self.url, current_line_number, current_line_number)
379 379 else:
380 380 yield 0, '<td class="line"><a href="">%i</a></td>' % (
381 381 current_line_number)
382 382 yield 0, '<td id="hlcode" class="code">' + line + '</td>'
383 383 yield 0, '</tr>'
384 384
385 385 last_shown_line_number = current_line_number
386 386
387 387 current_line_number += 1
388 388
389 389
390 390 yield 0, '</table>'
391 391
392 392
393 393 def extract_phrases(text_query):
394 394 """
395 395 Extracts phrases from search term string making sure phrases
396 396 contained in double quotes are kept together - and discarding empty values
397 397 or fully whitespace values eg.
398 398
399 399 'some text "a phrase" more' => ['some', 'text', 'a phrase', 'more']
400 400
401 401 """
402 402
403 403 in_phrase = False
404 404 buf = ''
405 405 phrases = []
406 406 for char in text_query:
407 407 if in_phrase:
408 408 if char == '"': # end phrase
409 409 phrases.append(buf)
410 410 buf = ''
411 411 in_phrase = False
412 412 continue
413 413 else:
414 414 buf += char
415 415 continue
416 416 else:
417 417 if char == '"': # start phrase
418 418 in_phrase = True
419 419 phrases.append(buf)
420 420 buf = ''
421 421 continue
422 422 elif char == ' ':
423 423 phrases.append(buf)
424 424 buf = ''
425 425 continue
426 426 else:
427 427 buf += char
428 428
429 429 phrases.append(buf)
430 430 phrases = [phrase.strip() for phrase in phrases if phrase.strip()]
431 431 return phrases
432 432
433 433
434 434 def get_matching_offsets(text, phrases):
435 435 """
436 436 Returns a list of string offsets in `text` that the list of `terms` match
437 437
438 438 >>> get_matching_offsets('some text here', ['some', 'here'])
439 439 [(0, 4), (10, 14)]
440 440
441 441 """
442 442 offsets = []
443 443 for phrase in phrases:
444 444 for match in re.finditer(phrase, text):
445 445 offsets.append((match.start(), match.end()))
446 446
447 447 return offsets
448 448
449 449
450 450 def normalize_text_for_matching(x):
451 451 """
452 452 Replaces all non alnum characters to spaces and lower cases the string,
453 453 useful for comparing two text strings without punctuation
454 454 """
455 455 return re.sub(r'[^\w]', ' ', x.lower())
456 456
457 457
458 458 def get_matching_line_offsets(lines, terms):
459 459 """ Return a set of `lines` indices (starting from 1) matching a
460 460 text search query, along with `context` lines above/below matching lines
461 461
462 462 :param lines: list of strings representing lines
463 463 :param terms: search term string to match in lines eg. 'some text'
464 464 :param context: number of lines above/below a matching line to add to result
465 465 :param max_lines: cut off for lines of interest
466 466 eg.
467 467
468 468 text = '''
469 469 words words words
470 470 words words words
471 471 some text some
472 472 words words words
473 473 words words words
474 474 text here what
475 475 '''
476 476 get_matching_line_offsets(text, 'text', context=1)
477 477 {3: [(5, 9)], 6: [(0, 4)]]
478 478
479 479 """
480 480 matching_lines = {}
481 481 phrases = [normalize_text_for_matching(phrase)
482 482 for phrase in extract_phrases(terms)]
483 483
484 484 for line_index, line in enumerate(lines, start=1):
485 485 match_offsets = get_matching_offsets(
486 486 normalize_text_for_matching(line), phrases)
487 487 if match_offsets:
488 488 matching_lines[line_index] = match_offsets
489 489
490 490 return matching_lines
491 491
492 492
493 493 def hsv_to_rgb(h, s, v):
494 494 """ Convert hsv color values to rgb """
495 495
496 496 if s == 0.0:
497 497 return v, v, v
498 498 i = int(h * 6.0) # XXX assume int() truncates!
499 499 f = (h * 6.0) - i
500 500 p = v * (1.0 - s)
501 501 q = v * (1.0 - s * f)
502 502 t = v * (1.0 - s * (1.0 - f))
503 503 i = i % 6
504 504 if i == 0:
505 505 return v, t, p
506 506 if i == 1:
507 507 return q, v, p
508 508 if i == 2:
509 509 return p, v, t
510 510 if i == 3:
511 511 return p, q, v
512 512 if i == 4:
513 513 return t, p, v
514 514 if i == 5:
515 515 return v, p, q
516 516
517 517
518 518 def unique_color_generator(n=10000, saturation=0.10, lightness=0.95):
519 519 """
520 520 Generator for getting n of evenly distributed colors using
521 521 hsv color and golden ratio. It always return same order of colors
522 522
523 523 :param n: number of colors to generate
524 524 :param saturation: saturation of returned colors
525 525 :param lightness: lightness of returned colors
526 526 :returns: RGB tuple
527 527 """
528 528
529 529 golden_ratio = 0.618033988749895
530 530 h = 0.22717784590367374
531 531
532 532 for _ in xrange(n):
533 533 h += golden_ratio
534 534 h %= 1
535 535 HSV_tuple = [h, saturation, lightness]
536 536 RGB_tuple = hsv_to_rgb(*HSV_tuple)
537 537 yield map(lambda x: str(int(x * 256)), RGB_tuple)
538 538
539 539
540 540 def color_hasher(n=10000, saturation=0.10, lightness=0.95):
541 541 """
542 542 Returns a function which when called with an argument returns a unique
543 543 color for that argument, eg.
544 544
545 545 :param n: number of colors to generate
546 546 :param saturation: saturation of returned colors
547 547 :param lightness: lightness of returned colors
548 548 :returns: css RGB string
549 549
550 550 >>> color_hash = color_hasher()
551 551 >>> color_hash('hello')
552 552 'rgb(34, 12, 59)'
553 553 >>> color_hash('hello')
554 554 'rgb(34, 12, 59)'
555 555 >>> color_hash('other')
556 556 'rgb(90, 224, 159)'
557 557 """
558 558
559 559 color_dict = {}
560 560 cgenerator = unique_color_generator(
561 561 saturation=saturation, lightness=lightness)
562 562
563 563 def get_color_string(thing):
564 564 if thing in color_dict:
565 565 col = color_dict[thing]
566 566 else:
567 567 col = color_dict[thing] = cgenerator.next()
568 568 return "rgb(%s)" % (', '.join(col))
569 569
570 570 return get_color_string
571 571
572 572
573 573 def get_lexer_safe(mimetype=None, filepath=None):
574 574 """
575 575 Tries to return a relevant pygments lexer using mimetype/filepath name,
576 576 defaulting to plain text if none could be found
577 577 """
578 578 lexer = None
579 579 try:
580 580 if mimetype:
581 581 lexer = get_lexer_for_mimetype(mimetype)
582 582 if not lexer:
583 583 lexer = get_lexer_for_filename(filepath)
584 584 except pygments.util.ClassNotFound:
585 585 pass
586 586
587 587 if not lexer:
588 588 lexer = get_lexer_by_name('text')
589 589
590 590 return lexer
591 591
592 592
593 593 def get_lexer_for_filenode(filenode):
594 594 lexer = get_custom_lexer(filenode.extension) or filenode.lexer
595 595 return lexer
596 596
597 597
598 598 def pygmentize(filenode, **kwargs):
599 599 """
600 600 pygmentize function using pygments
601 601
602 602 :param filenode:
603 603 """
604 604 lexer = get_lexer_for_filenode(filenode)
605 605 return literal(code_highlight(filenode.content, lexer,
606 606 CodeHtmlFormatter(**kwargs)))
607 607
608 608
609 609 def is_following_repo(repo_name, user_id):
610 610 from rhodecode.model.scm import ScmModel
611 611 return ScmModel().is_following_repo(repo_name, user_id)
612 612
613 613
614 614 class _Message(object):
615 615 """A message returned by ``Flash.pop_messages()``.
616 616
617 617 Converting the message to a string returns the message text. Instances
618 618 also have the following attributes:
619 619
620 620 * ``message``: the message text.
621 621 * ``category``: the category specified when the message was created.
622 622 """
623 623
624 624 def __init__(self, category, message):
625 625 self.category = category
626 626 self.message = message
627 627
628 628 def __str__(self):
629 629 return self.message
630 630
631 631 __unicode__ = __str__
632 632
633 633 def __html__(self):
634 634 return escape(safe_unicode(self.message))
635 635
636 636
637 637 class Flash(object):
638 638 # List of allowed categories. If None, allow any category.
639 639 categories = ["warning", "notice", "error", "success"]
640 640
641 641 # Default category if none is specified.
642 642 default_category = "notice"
643 643
644 644 def __init__(self, session_key="flash", categories=None,
645 645 default_category=None):
646 646 """
647 647 Instantiate a ``Flash`` object.
648 648
649 649 ``session_key`` is the key to save the messages under in the user's
650 650 session.
651 651
652 652 ``categories`` is an optional list which overrides the default list
653 653 of categories.
654 654
655 655 ``default_category`` overrides the default category used for messages
656 656 when none is specified.
657 657 """
658 658 self.session_key = session_key
659 659 if categories is not None:
660 660 self.categories = categories
661 661 if default_category is not None:
662 662 self.default_category = default_category
663 663 if self.categories and self.default_category not in self.categories:
664 664 raise ValueError(
665 665 "unrecognized default category %r" % (self.default_category,))
666 666
667 667 def pop_messages(self, session=None, request=None):
668 668 """
669 669 Return all accumulated messages and delete them from the session.
670 670
671 671 The return value is a list of ``Message`` objects.
672 672 """
673 673 messages = []
674 674
675 675 if not session:
676 676 if not request:
677 677 request = get_current_request()
678 678 session = request.session
679 679
680 680 # Pop the 'old' pylons flash messages. They are tuples of the form
681 681 # (category, message)
682 682 for cat, msg in session.pop(self.session_key, []):
683 683 messages.append(_Message(cat, msg))
684 684
685 685 # Pop the 'new' pyramid flash messages for each category as list
686 686 # of strings.
687 687 for cat in self.categories:
688 688 for msg in session.pop_flash(queue=cat):
689 689 messages.append(_Message(cat, msg))
690 690 # Map messages from the default queue to the 'notice' category.
691 691 for msg in session.pop_flash():
692 692 messages.append(_Message('notice', msg))
693 693
694 694 session.save()
695 695 return messages
696 696
697 697 def json_alerts(self, session=None, request=None):
698 698 payloads = []
699 699 messages = flash.pop_messages(session=session, request=request)
700 700 if messages:
701 701 for message in messages:
702 702 subdata = {}
703 703 if hasattr(message.message, 'rsplit'):
704 704 flash_data = message.message.rsplit('|DELIM|', 1)
705 705 org_message = flash_data[0]
706 706 if len(flash_data) > 1:
707 707 subdata = json.loads(flash_data[1])
708 708 else:
709 709 org_message = message.message
710 710 payloads.append({
711 711 'message': {
712 712 'message': u'{}'.format(org_message),
713 713 'level': message.category,
714 714 'force': True,
715 715 'subdata': subdata
716 716 }
717 717 })
718 718 return json.dumps(payloads)
719 719
720 720 def __call__(self, message, category=None, ignore_duplicate=False,
721 721 session=None, request=None):
722 722
723 723 if not session:
724 724 if not request:
725 725 request = get_current_request()
726 726 session = request.session
727 727
728 728 session.flash(
729 729 message, queue=category, allow_duplicate=not ignore_duplicate)
730 730
731 731
732 732 flash = Flash()
733 733
734 734 #==============================================================================
735 735 # SCM FILTERS available via h.
736 736 #==============================================================================
737 737 from rhodecode.lib.vcs.utils import author_name, author_email
738 738 from rhodecode.lib.utils2 import credentials_filter, age as _age
739 739 from rhodecode.model.db import User, ChangesetStatus
740 740
741 741 age = _age
742 742 capitalize = lambda x: x.capitalize()
743 743 email = author_email
744 744 short_id = lambda x: x[:12]
745 745 hide_credentials = lambda x: ''.join(credentials_filter(x))
746 746
747 747
748 748 import pytz
749 749 import tzlocal
750 750 local_timezone = tzlocal.get_localzone()
751 751
752 752
753 753 def age_component(datetime_iso, value=None, time_is_local=False):
754 754 title = value or format_date(datetime_iso)
755 755 tzinfo = '+00:00'
756 756
757 757 # detect if we have a timezone info, otherwise, add it
758 758 if time_is_local and isinstance(datetime_iso, datetime) and not datetime_iso.tzinfo:
759 759 force_timezone = os.environ.get('RC_TIMEZONE', '')
760 760 if force_timezone:
761 761 force_timezone = pytz.timezone(force_timezone)
762 762 timezone = force_timezone or local_timezone
763 763 offset = timezone.localize(datetime_iso).strftime('%z')
764 764 tzinfo = '{}:{}'.format(offset[:-2], offset[-2:])
765 765
766 766 return literal(
767 767 '<time class="timeago tooltip" '
768 768 'title="{1}{2}" datetime="{0}{2}">{1}</time>'.format(
769 769 datetime_iso, title, tzinfo))
770 770
771 771
772 772 def _shorten_commit_id(commit_id):
773 773 from rhodecode import CONFIG
774 774 def_len = safe_int(CONFIG.get('rhodecode_show_sha_length', 12))
775 775 return commit_id[:def_len]
776 776
777 777
778 778 def show_id(commit):
779 779 """
780 780 Configurable function that shows ID
781 781 by default it's r123:fffeeefffeee
782 782
783 783 :param commit: commit instance
784 784 """
785 785 from rhodecode import CONFIG
786 786 show_idx = str2bool(CONFIG.get('rhodecode_show_revision_number', True))
787 787
788 788 raw_id = _shorten_commit_id(commit.raw_id)
789 789 if show_idx:
790 790 return 'r%s:%s' % (commit.idx, raw_id)
791 791 else:
792 792 return '%s' % (raw_id, )
793 793
794 794
795 795 def format_date(date):
796 796 """
797 797 use a standardized formatting for dates used in RhodeCode
798 798
799 799 :param date: date/datetime object
800 800 :return: formatted date
801 801 """
802 802
803 803 if date:
804 804 _fmt = "%a, %d %b %Y %H:%M:%S"
805 805 return safe_unicode(date.strftime(_fmt))
806 806
807 807 return u""
808 808
809 809
810 810 class _RepoChecker(object):
811 811
812 812 def __init__(self, backend_alias):
813 813 self._backend_alias = backend_alias
814 814
815 815 def __call__(self, repository):
816 816 if hasattr(repository, 'alias'):
817 817 _type = repository.alias
818 818 elif hasattr(repository, 'repo_type'):
819 819 _type = repository.repo_type
820 820 else:
821 821 _type = repository
822 822 return _type == self._backend_alias
823 823
824 824 is_git = _RepoChecker('git')
825 825 is_hg = _RepoChecker('hg')
826 826 is_svn = _RepoChecker('svn')
827 827
828 828
829 829 def get_repo_type_by_name(repo_name):
830 830 repo = Repository.get_by_repo_name(repo_name)
831 831 return repo.repo_type
832 832
833 833
834 834 def is_svn_without_proxy(repository):
835 835 if is_svn(repository):
836 836 from rhodecode.model.settings import VcsSettingsModel
837 837 conf = VcsSettingsModel().get_ui_settings_as_config_obj()
838 838 return not str2bool(conf.get('vcs_svn_proxy', 'http_requests_enabled'))
839 839 return False
840 840
841 841
842 842 def discover_user(author):
843 843 """
844 844 Tries to discover RhodeCode User based on the autho string. Author string
845 845 is typically `FirstName LastName <email@address.com>`
846 846 """
847 847
848 848 # if author is already an instance use it for extraction
849 849 if isinstance(author, User):
850 850 return author
851 851
852 852 # Valid email in the attribute passed, see if they're in the system
853 853 _email = author_email(author)
854 854 if _email != '':
855 855 user = User.get_by_email(_email, case_insensitive=True, cache=True)
856 856 if user is not None:
857 857 return user
858 858
859 859 # Maybe it's a username, we try to extract it and fetch by username ?
860 860 _author = author_name(author)
861 861 user = User.get_by_username(_author, case_insensitive=True, cache=True)
862 862 if user is not None:
863 863 return user
864 864
865 865 return None
866 866
867 867
868 868 def email_or_none(author):
869 869 # extract email from the commit string
870 870 _email = author_email(author)
871 871
872 872 # If we have an email, use it, otherwise
873 873 # see if it contains a username we can get an email from
874 874 if _email != '':
875 875 return _email
876 876 else:
877 877 user = User.get_by_username(
878 878 author_name(author), case_insensitive=True, cache=True)
879 879
880 880 if user is not None:
881 881 return user.email
882 882
883 883 # No valid email, not a valid user in the system, none!
884 884 return None
885 885
886 886
887 887 def link_to_user(author, length=0, **kwargs):
888 888 user = discover_user(author)
889 889 # user can be None, but if we have it already it means we can re-use it
890 890 # in the person() function, so we save 1 intensive-query
891 891 if user:
892 892 author = user
893 893
894 894 display_person = person(author, 'username_or_name_or_email')
895 895 if length:
896 896 display_person = shorter(display_person, length)
897 897
898 898 if user:
899 899 return link_to(
900 900 escape(display_person),
901 901 route_path('user_profile', username=user.username),
902 902 **kwargs)
903 903 else:
904 904 return escape(display_person)
905 905
906 906
907 907 def link_to_group(users_group_name, **kwargs):
908 908 return link_to(
909 909 escape(users_group_name),
910 910 route_path('user_group_profile', user_group_name=users_group_name),
911 911 **kwargs)
912 912
913 913
914 914 def person(author, show_attr="username_and_name"):
915 915 user = discover_user(author)
916 916 if user:
917 917 return getattr(user, show_attr)
918 918 else:
919 919 _author = author_name(author)
920 920 _email = email(author)
921 921 return _author or _email
922 922
923 923
924 924 def author_string(email):
925 925 if email:
926 926 user = User.get_by_email(email, case_insensitive=True, cache=True)
927 927 if user:
928 928 if user.first_name or user.last_name:
929 929 return '%s %s &lt;%s&gt;' % (
930 930 user.first_name, user.last_name, email)
931 931 else:
932 932 return email
933 933 else:
934 934 return email
935 935 else:
936 936 return None
937 937
938 938
939 939 def person_by_id(id_, show_attr="username_and_name"):
940 940 # attr to return from fetched user
941 941 person_getter = lambda usr: getattr(usr, show_attr)
942 942
943 943 #maybe it's an ID ?
944 944 if str(id_).isdigit() or isinstance(id_, int):
945 945 id_ = int(id_)
946 946 user = User.get(id_)
947 947 if user is not None:
948 948 return person_getter(user)
949 949 return id_
950 950
951 951
952 952 def gravatar_with_user(request, author, show_disabled=False):
953 953 _render = request.get_partial_renderer(
954 954 'rhodecode:templates/base/base.mako')
955 955 return _render('gravatar_with_user', author, show_disabled=show_disabled)
956 956
957 957
958 958 tags_paterns = OrderedDict((
959 959 ('lang', (re.compile(r'\[(lang|language)\ \=\&gt;\ *([a-zA-Z\-\/\#\+\.]*)\]'),
960 960 '<div class="metatag" tag="lang">\\2</div>')),
961 961
962 962 ('see', (re.compile(r'\[see\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]'),
963 963 '<div class="metatag" tag="see">see: \\1 </div>')),
964 964
965 965 ('url', (re.compile(r'\[url\ \=\&gt;\ \[([a-zA-Z0-9\ \.\-\_]+)\]\((http://|https://|/)(.*?)\)\]'),
966 966 '<div class="metatag" tag="url"> <a href="\\2\\3">\\1</a> </div>')),
967 967
968 968 ('license', (re.compile(r'\[license\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]'),
969 969 '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/\\1">\\1</a></div>')),
970 970
971 971 ('ref', (re.compile(r'\[(requires|recommends|conflicts|base)\ \=\&gt;\ *([a-zA-Z0-9\-\/]*)\]'),
972 972 '<div class="metatag" tag="ref \\1">\\1: <a href="/\\2">\\2</a></div>')),
973 973
974 974 ('state', (re.compile(r'\[(stable|featured|stale|dead|dev|deprecated)\]'),
975 975 '<div class="metatag" tag="state \\1">\\1</div>')),
976 976
977 977 # label in grey
978 978 ('label', (re.compile(r'\[([a-z]+)\]'),
979 979 '<div class="metatag" tag="label">\\1</div>')),
980 980
981 981 # generic catch all in grey
982 982 ('generic', (re.compile(r'\[([a-zA-Z0-9\.\-\_]+)\]'),
983 983 '<div class="metatag" tag="generic">\\1</div>')),
984 984 ))
985 985
986 986
987 987 def extract_metatags(value):
988 988 """
989 989 Extract supported meta-tags from given text value
990 990 """
991 991 tags = []
992 992 if not value:
993 993 return tags, ''
994 994
995 995 for key, val in tags_paterns.items():
996 996 pat, replace_html = val
997 997 tags.extend([(key, x.group()) for x in pat.finditer(value)])
998 998 value = pat.sub('', value)
999 999
1000 1000 return tags, value
1001 1001
1002 1002
1003 1003 def style_metatag(tag_type, value):
1004 1004 """
1005 1005 converts tags from value into html equivalent
1006 1006 """
1007 1007 if not value:
1008 1008 return ''
1009 1009
1010 1010 html_value = value
1011 1011 tag_data = tags_paterns.get(tag_type)
1012 1012 if tag_data:
1013 1013 pat, replace_html = tag_data
1014 1014 # convert to plain `unicode` instead of a markup tag to be used in
1015 1015 # regex expressions. safe_unicode doesn't work here
1016 1016 html_value = pat.sub(replace_html, unicode(value))
1017 1017
1018 1018 return html_value
1019 1019
1020 1020
1021 1021 def bool2icon(value):
1022 1022 """
1023 1023 Returns boolean value of a given value, represented as html element with
1024 1024 classes that will represent icons
1025 1025
1026 1026 :param value: given value to convert to html node
1027 1027 """
1028 1028
1029 1029 if value: # does bool conversion
1030 1030 return HTML.tag('i', class_="icon-true")
1031 1031 else: # not true as bool
1032 1032 return HTML.tag('i', class_="icon-false")
1033 1033
1034 1034
1035 1035 #==============================================================================
1036 1036 # PERMS
1037 1037 #==============================================================================
1038 1038 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
1039 1039 HasRepoPermissionAny, HasRepoPermissionAll, HasRepoGroupPermissionAll, \
1040 1040 HasRepoGroupPermissionAny, HasRepoPermissionAnyApi, get_csrf_token, \
1041 1041 csrf_token_key
1042 1042
1043 1043
1044 1044 #==============================================================================
1045 1045 # GRAVATAR URL
1046 1046 #==============================================================================
1047 1047 class InitialsGravatar(object):
1048 1048 def __init__(self, email_address, first_name, last_name, size=30,
1049 1049 background=None, text_color='#fff'):
1050 1050 self.size = size
1051 1051 self.first_name = first_name
1052 1052 self.last_name = last_name
1053 1053 self.email_address = email_address
1054 1054 self.background = background or self.str2color(email_address)
1055 1055 self.text_color = text_color
1056 1056
1057 1057 def get_color_bank(self):
1058 1058 """
1059 1059 returns a predefined list of colors that gravatars can use.
1060 1060 Those are randomized distinct colors that guarantee readability and
1061 1061 uniqueness.
1062 1062
1063 1063 generated with: http://phrogz.net/css/distinct-colors.html
1064 1064 """
1065 1065 return [
1066 1066 '#bf3030', '#a67f53', '#00ff00', '#5989b3', '#392040', '#d90000',
1067 1067 '#402910', '#204020', '#79baf2', '#a700b3', '#bf6060', '#7f5320',
1068 1068 '#008000', '#003059', '#ee00ff', '#ff0000', '#8c4b00', '#007300',
1069 1069 '#005fb3', '#de73e6', '#ff4040', '#ffaa00', '#3df255', '#203140',
1070 1070 '#47004d', '#591616', '#664400', '#59b365', '#0d2133', '#83008c',
1071 1071 '#592d2d', '#bf9f60', '#73e682', '#1d3f73', '#73006b', '#402020',
1072 1072 '#b2862d', '#397341', '#597db3', '#e600d6', '#a60000', '#736039',
1073 1073 '#00b318', '#79aaf2', '#330d30', '#ff8080', '#403010', '#16591f',
1074 1074 '#002459', '#8c4688', '#e50000', '#ffbf40', '#00732e', '#102340',
1075 1075 '#bf60ac', '#8c4646', '#cc8800', '#00a642', '#1d3473', '#b32d98',
1076 1076 '#660e00', '#ffd580', '#80ffb2', '#7391e6', '#733967', '#d97b6c',
1077 1077 '#8c5e00', '#59b389', '#3967e6', '#590047', '#73281d', '#665200',
1078 1078 '#00e67a', '#2d50b3', '#8c2377', '#734139', '#b2982d', '#16593a',
1079 1079 '#001859', '#ff00aa', '#a65e53', '#ffcc00', '#0d3321', '#2d3959',
1080 1080 '#731d56', '#401610', '#4c3d00', '#468c6c', '#002ca6', '#d936a3',
1081 1081 '#d94c36', '#403920', '#36d9a3', '#0d1733', '#592d4a', '#993626',
1082 1082 '#cca300', '#00734d', '#46598c', '#8c005e', '#7f1100', '#8c7000',
1083 1083 '#00a66f', '#7382e6', '#b32d74', '#d9896c', '#ffe680', '#1d7362',
1084 1084 '#364cd9', '#73003d', '#d93a00', '#998a4d', '#59b3a1', '#5965b3',
1085 1085 '#e5007a', '#73341d', '#665f00', '#00b38f', '#0018b3', '#59163a',
1086 1086 '#b2502d', '#bfb960', '#00ffcc', '#23318c', '#a6537f', '#734939',
1087 1087 '#b2a700', '#104036', '#3d3df2', '#402031', '#e56739', '#736f39',
1088 1088 '#79f2ea', '#000059', '#401029', '#4c1400', '#ffee00', '#005953',
1089 1089 '#101040', '#990052', '#402820', '#403d10', '#00ffee', '#0000d9',
1090 1090 '#ff80c4', '#a66953', '#eeff00', '#00ccbe', '#8080ff', '#e673a1',
1091 1091 '#a62c00', '#474d00', '#1a3331', '#46468c', '#733950', '#662900',
1092 1092 '#858c23', '#238c85', '#0f0073', '#b20047', '#d9986c', '#becc00',
1093 1093 '#396f73', '#281d73', '#ff0066', '#ff6600', '#dee673', '#59adb3',
1094 1094 '#6559b3', '#590024', '#b2622d', '#98b32d', '#36ced9', '#332d59',
1095 1095 '#40001a', '#733f1d', '#526600', '#005359', '#242040', '#bf6079',
1096 1096 '#735039', '#cef23d', '#007780', '#5630bf', '#66001b', '#b24700',
1097 1097 '#acbf60', '#1d6273', '#25008c', '#731d34', '#a67453', '#50592d',
1098 1098 '#00ccff', '#6600ff', '#ff0044', '#4c1f00', '#8a994d', '#79daf2',
1099 1099 '#a173e6', '#d93662', '#402310', '#aaff00', '#2d98b3', '#8c40ff',
1100 1100 '#592d39', '#ff8c40', '#354020', '#103640', '#1a0040', '#331a20',
1101 1101 '#331400', '#334d00', '#1d5673', '#583973', '#7f0022', '#4c3626',
1102 1102 '#88cc00', '#36a3d9', '#3d0073', '#d9364c', '#33241a', '#698c23',
1103 1103 '#5995b3', '#300059', '#e57382', '#7f3300', '#366600', '#00aaff',
1104 1104 '#3a1659', '#733941', '#663600', '#74b32d', '#003c59', '#7f53a6',
1105 1105 '#73000f', '#ff8800', '#baf279', '#79caf2', '#291040', '#a6293a',
1106 1106 '#b2742d', '#587339', '#0077b3', '#632699', '#400009', '#d9a66c',
1107 1107 '#294010', '#2d4a59', '#aa00ff', '#4c131b', '#b25f00', '#5ce600',
1108 1108 '#267399', '#a336d9', '#990014', '#664e33', '#86bf60', '#0088ff',
1109 1109 '#7700b3', '#593a16', '#073300', '#1d4b73', '#ac60bf', '#e59539',
1110 1110 '#4f8c46', '#368dd9', '#5c0073'
1111 1111 ]
1112 1112
1113 1113 def rgb_to_hex_color(self, rgb_tuple):
1114 1114 """
1115 1115 Converts an rgb_tuple passed to an hex color.
1116 1116
1117 1117 :param rgb_tuple: tuple with 3 ints represents rgb color space
1118 1118 """
1119 1119 return '#' + ("".join(map(chr, rgb_tuple)).encode('hex'))
1120 1120
1121 1121 def email_to_int_list(self, email_str):
1122 1122 """
1123 1123 Get every byte of the hex digest value of email and turn it to integer.
1124 1124 It's going to be always between 0-255
1125 1125 """
1126 1126 digest = md5_safe(email_str.lower())
1127 1127 return [int(digest[i * 2:i * 2 + 2], 16) for i in range(16)]
1128 1128
1129 1129 def pick_color_bank_index(self, email_str, color_bank):
1130 1130 return self.email_to_int_list(email_str)[0] % len(color_bank)
1131 1131
1132 1132 def str2color(self, email_str):
1133 1133 """
1134 1134 Tries to map in a stable algorithm an email to color
1135 1135
1136 1136 :param email_str:
1137 1137 """
1138 1138 color_bank = self.get_color_bank()
1139 1139 # pick position (module it's length so we always find it in the
1140 1140 # bank even if it's smaller than 256 values
1141 1141 pos = self.pick_color_bank_index(email_str, color_bank)
1142 1142 return color_bank[pos]
1143 1143
1144 1144 def normalize_email(self, email_address):
1145 1145 import unicodedata
1146 1146 # default host used to fill in the fake/missing email
1147 1147 default_host = u'localhost'
1148 1148
1149 1149 if not email_address:
1150 1150 email_address = u'%s@%s' % (User.DEFAULT_USER, default_host)
1151 1151
1152 1152 email_address = safe_unicode(email_address)
1153 1153
1154 1154 if u'@' not in email_address:
1155 1155 email_address = u'%s@%s' % (email_address, default_host)
1156 1156
1157 1157 if email_address.endswith(u'@'):
1158 1158 email_address = u'%s%s' % (email_address, default_host)
1159 1159
1160 1160 email_address = unicodedata.normalize('NFKD', email_address)\
1161 1161 .encode('ascii', 'ignore')
1162 1162 return email_address
1163 1163
1164 1164 def get_initials(self):
1165 1165 """
1166 1166 Returns 2 letter initials calculated based on the input.
1167 1167 The algorithm picks first given email address, and takes first letter
1168 1168 of part before @, and then the first letter of server name. In case
1169 1169 the part before @ is in a format of `somestring.somestring2` it replaces
1170 1170 the server letter with first letter of somestring2
1171 1171
1172 1172 In case function was initialized with both first and lastname, this
1173 1173 overrides the extraction from email by first letter of the first and
1174 1174 last name. We add special logic to that functionality, In case Full name
1175 1175 is compound, like Guido Von Rossum, we use last part of the last name
1176 1176 (Von Rossum) picking `R`.
1177 1177
1178 1178 Function also normalizes the non-ascii characters to they ascii
1179 1179 representation, eg Ą => A
1180 1180 """
1181 1181 import unicodedata
1182 1182 # replace non-ascii to ascii
1183 1183 first_name = unicodedata.normalize(
1184 1184 'NFKD', safe_unicode(self.first_name)).encode('ascii', 'ignore')
1185 1185 last_name = unicodedata.normalize(
1186 1186 'NFKD', safe_unicode(self.last_name)).encode('ascii', 'ignore')
1187 1187
1188 1188 # do NFKD encoding, and also make sure email has proper format
1189 1189 email_address = self.normalize_email(self.email_address)
1190 1190
1191 1191 # first push the email initials
1192 1192 prefix, server = email_address.split('@', 1)
1193 1193
1194 1194 # check if prefix is maybe a 'first_name.last_name' syntax
1195 1195 _dot_split = prefix.rsplit('.', 1)
1196 1196 if len(_dot_split) == 2 and _dot_split[1]:
1197 1197 initials = [_dot_split[0][0], _dot_split[1][0]]
1198 1198 else:
1199 1199 initials = [prefix[0], server[0]]
1200 1200
1201 1201 # then try to replace either first_name or last_name
1202 1202 fn_letter = (first_name or " ")[0].strip()
1203 1203 ln_letter = (last_name.split(' ', 1)[-1] or " ")[0].strip()
1204 1204
1205 1205 if fn_letter:
1206 1206 initials[0] = fn_letter
1207 1207
1208 1208 if ln_letter:
1209 1209 initials[1] = ln_letter
1210 1210
1211 1211 return ''.join(initials).upper()
1212 1212
1213 1213 def get_img_data_by_type(self, font_family, img_type):
1214 1214 default_user = """
1215 1215 <svg xmlns="http://www.w3.org/2000/svg"
1216 1216 version="1.1" x="0px" y="0px" width="{size}" height="{size}"
1217 1217 viewBox="-15 -10 439.165 429.164"
1218 1218
1219 1219 xml:space="preserve"
1220 1220 style="background:{background};" >
1221 1221
1222 1222 <path d="M204.583,216.671c50.664,0,91.74-48.075,
1223 1223 91.74-107.378c0-82.237-41.074-107.377-91.74-107.377
1224 1224 c-50.668,0-91.74,25.14-91.74,107.377C112.844,
1225 1225 168.596,153.916,216.671,
1226 1226 204.583,216.671z" fill="{text_color}"/>
1227 1227 <path d="M407.164,374.717L360.88,
1228 1228 270.454c-2.117-4.771-5.836-8.728-10.465-11.138l-71.83-37.392
1229 1229 c-1.584-0.823-3.502-0.663-4.926,0.415c-20.316,
1230 1230 15.366-44.203,23.488-69.076,23.488c-24.877,
1231 1231 0-48.762-8.122-69.078-23.488
1232 1232 c-1.428-1.078-3.346-1.238-4.93-0.415L58.75,
1233 1233 259.316c-4.631,2.41-8.346,6.365-10.465,11.138L2.001,374.717
1234 1234 c-3.191,7.188-2.537,15.412,1.75,22.005c4.285,
1235 1235 6.592,11.537,10.526,19.4,10.526h362.861c7.863,0,15.117-3.936,
1236 1236 19.402-10.527 C409.699,390.129,
1237 1237 410.355,381.902,407.164,374.717z" fill="{text_color}"/>
1238 1238 </svg>""".format(
1239 1239 size=self.size,
1240 1240 background='#979797', # @grey4
1241 1241 text_color=self.text_color,
1242 1242 font_family=font_family)
1243 1243
1244 1244 return {
1245 1245 "default_user": default_user
1246 1246 }[img_type]
1247 1247
1248 1248 def get_img_data(self, svg_type=None):
1249 1249 """
1250 1250 generates the svg metadata for image
1251 1251 """
1252
1253 font_family = ','.join([
1254 'proximanovaregular',
1255 'Proxima Nova Regular',
1256 'Proxima Nova',
1257 'Arial',
1258 'Lucida Grande',
1259 'sans-serif'
1260 ])
1252 fonts = [
1253 '-apple-system',
1254 'BlinkMacSystemFont',
1255 'Segoe UI',
1256 'Roboto',
1257 'Oxygen-Sans',
1258 'Ubuntu',
1259 'Cantarell',
1260 'Helvetica Neue',
1261 'sans-serif'
1262 ]
1263 font_family = ','.join(fonts)
1261 1264 if svg_type:
1262 1265 return self.get_img_data_by_type(font_family, svg_type)
1263 1266
1264 1267 initials = self.get_initials()
1265 1268 img_data = """
1266 1269 <svg xmlns="http://www.w3.org/2000/svg" pointer-events="none"
1267 1270 width="{size}" height="{size}"
1268 1271 style="width: 100%; height: 100%; background-color: {background}"
1269 1272 viewBox="0 0 {size} {size}">
1270 1273 <text text-anchor="middle" y="50%" x="50%" dy="0.35em"
1271 1274 pointer-events="auto" fill="{text_color}"
1272 1275 font-family="{font_family}"
1273 1276 style="font-weight: 400; font-size: {f_size}px;">{text}
1274 1277 </text>
1275 1278 </svg>""".format(
1276 1279 size=self.size,
1277 1280 f_size=self.size/1.85, # scale the text inside the box nicely
1278 1281 background=self.background,
1279 1282 text_color=self.text_color,
1280 1283 text=initials.upper(),
1281 1284 font_family=font_family)
1282 1285
1283 1286 return img_data
1284 1287
1285 1288 def generate_svg(self, svg_type=None):
1286 1289 img_data = self.get_img_data(svg_type)
1287 1290 return "data:image/svg+xml;base64,%s" % img_data.encode('base64')
1288 1291
1289 1292
1290 1293 def initials_gravatar(email_address, first_name, last_name, size=30):
1291 1294 svg_type = None
1292 1295 if email_address == User.DEFAULT_USER_EMAIL:
1293 1296 svg_type = 'default_user'
1294 1297 klass = InitialsGravatar(email_address, first_name, last_name, size)
1295 1298 return klass.generate_svg(svg_type=svg_type)
1296 1299
1297 1300
1298 1301 def gravatar_url(email_address, size=30, request=None):
1299 1302 request = get_current_request()
1300 1303 _use_gravatar = request.call_context.visual.use_gravatar
1301 1304 _gravatar_url = request.call_context.visual.gravatar_url
1302 1305
1303 1306 _gravatar_url = _gravatar_url or User.DEFAULT_GRAVATAR_URL
1304 1307
1305 1308 email_address = email_address or User.DEFAULT_USER_EMAIL
1306 1309 if isinstance(email_address, unicode):
1307 1310 # hashlib crashes on unicode items
1308 1311 email_address = safe_str(email_address)
1309 1312
1310 1313 # empty email or default user
1311 1314 if not email_address or email_address == User.DEFAULT_USER_EMAIL:
1312 1315 return initials_gravatar(User.DEFAULT_USER_EMAIL, '', '', size=size)
1313 1316
1314 1317 if _use_gravatar:
1315 1318 # TODO: Disuse pyramid thread locals. Think about another solution to
1316 1319 # get the host and schema here.
1317 1320 request = get_current_request()
1318 1321 tmpl = safe_str(_gravatar_url)
1319 1322 tmpl = tmpl.replace('{email}', email_address)\
1320 1323 .replace('{md5email}', md5_safe(email_address.lower())) \
1321 1324 .replace('{netloc}', request.host)\
1322 1325 .replace('{scheme}', request.scheme)\
1323 1326 .replace('{size}', safe_str(size))
1324 1327 return tmpl
1325 1328 else:
1326 1329 return initials_gravatar(email_address, '', '', size=size)
1327 1330
1328 1331
1329 1332 class Page(_Page):
1330 1333 """
1331 1334 Custom pager to match rendering style with paginator
1332 1335 """
1333 1336
1334 1337 def _get_pos(self, cur_page, max_page, items):
1335 1338 edge = (items / 2) + 1
1336 1339 if (cur_page <= edge):
1337 1340 radius = max(items / 2, items - cur_page)
1338 1341 elif (max_page - cur_page) < edge:
1339 1342 radius = (items - 1) - (max_page - cur_page)
1340 1343 else:
1341 1344 radius = items / 2
1342 1345
1343 1346 left = max(1, (cur_page - (radius)))
1344 1347 right = min(max_page, cur_page + (radius))
1345 1348 return left, cur_page, right
1346 1349
1347 1350 def _range(self, regexp_match):
1348 1351 """
1349 1352 Return range of linked pages (e.g. '1 2 [3] 4 5 6 7 8').
1350 1353
1351 1354 Arguments:
1352 1355
1353 1356 regexp_match
1354 1357 A "re" (regular expressions) match object containing the
1355 1358 radius of linked pages around the current page in
1356 1359 regexp_match.group(1) as a string
1357 1360
1358 1361 This function is supposed to be called as a callable in
1359 1362 re.sub.
1360 1363
1361 1364 """
1362 1365 radius = int(regexp_match.group(1))
1363 1366
1364 1367 # Compute the first and last page number within the radius
1365 1368 # e.g. '1 .. 5 6 [7] 8 9 .. 12'
1366 1369 # -> leftmost_page = 5
1367 1370 # -> rightmost_page = 9
1368 1371 leftmost_page, _cur, rightmost_page = self._get_pos(self.page,
1369 1372 self.last_page,
1370 1373 (radius * 2) + 1)
1371 1374 nav_items = []
1372 1375
1373 1376 # Create a link to the first page (unless we are on the first page
1374 1377 # or there would be no need to insert '..' spacers)
1375 1378 if self.page != self.first_page and self.first_page < leftmost_page:
1376 1379 nav_items.append(self._pagerlink(self.first_page, self.first_page))
1377 1380
1378 1381 # Insert dots if there are pages between the first page
1379 1382 # and the currently displayed page range
1380 1383 if leftmost_page - self.first_page > 1:
1381 1384 # Wrap in a SPAN tag if nolink_attr is set
1382 1385 text = '..'
1383 1386 if self.dotdot_attr:
1384 1387 text = HTML.span(c=text, **self.dotdot_attr)
1385 1388 nav_items.append(text)
1386 1389
1387 1390 for thispage in xrange(leftmost_page, rightmost_page + 1):
1388 1391 # Hilight the current page number and do not use a link
1389 1392 if thispage == self.page:
1390 1393 text = '%s' % (thispage,)
1391 1394 # Wrap in a SPAN tag if nolink_attr is set
1392 1395 if self.curpage_attr:
1393 1396 text = HTML.span(c=text, **self.curpage_attr)
1394 1397 nav_items.append(text)
1395 1398 # Otherwise create just a link to that page
1396 1399 else:
1397 1400 text = '%s' % (thispage,)
1398 1401 nav_items.append(self._pagerlink(thispage, text))
1399 1402
1400 1403 # Insert dots if there are pages between the displayed
1401 1404 # page numbers and the end of the page range
1402 1405 if self.last_page - rightmost_page > 1:
1403 1406 text = '..'
1404 1407 # Wrap in a SPAN tag if nolink_attr is set
1405 1408 if self.dotdot_attr:
1406 1409 text = HTML.span(c=text, **self.dotdot_attr)
1407 1410 nav_items.append(text)
1408 1411
1409 1412 # Create a link to the very last page (unless we are on the last
1410 1413 # page or there would be no need to insert '..' spacers)
1411 1414 if self.page != self.last_page and rightmost_page < self.last_page:
1412 1415 nav_items.append(self._pagerlink(self.last_page, self.last_page))
1413 1416
1414 1417 ## prerender links
1415 1418 #_page_link = url.current()
1416 1419 #nav_items.append(literal('<link rel="prerender" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
1417 1420 #nav_items.append(literal('<link rel="prefetch" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
1418 1421 return self.separator.join(nav_items)
1419 1422
1420 1423 def pager(self, format='~2~', page_param='page', partial_param='partial',
1421 1424 show_if_single_page=False, separator=' ', onclick=None,
1422 1425 symbol_first='<<', symbol_last='>>',
1423 1426 symbol_previous='<', symbol_next='>',
1424 1427 link_attr={'class': 'pager_link', 'rel': 'prerender'},
1425 1428 curpage_attr={'class': 'pager_curpage'},
1426 1429 dotdot_attr={'class': 'pager_dotdot'}, **kwargs):
1427 1430
1428 1431 self.curpage_attr = curpage_attr
1429 1432 self.separator = separator
1430 1433 self.pager_kwargs = kwargs
1431 1434 self.page_param = page_param
1432 1435 self.partial_param = partial_param
1433 1436 self.onclick = onclick
1434 1437 self.link_attr = link_attr
1435 1438 self.dotdot_attr = dotdot_attr
1436 1439
1437 1440 # Don't show navigator if there is no more than one page
1438 1441 if self.page_count == 0 or (self.page_count == 1 and not show_if_single_page):
1439 1442 return ''
1440 1443
1441 1444 from string import Template
1442 1445 # Replace ~...~ in token format by range of pages
1443 1446 result = re.sub(r'~(\d+)~', self._range, format)
1444 1447
1445 1448 # Interpolate '%' variables
1446 1449 result = Template(result).safe_substitute({
1447 1450 'first_page': self.first_page,
1448 1451 'last_page': self.last_page,
1449 1452 'page': self.page,
1450 1453 'page_count': self.page_count,
1451 1454 'items_per_page': self.items_per_page,
1452 1455 'first_item': self.first_item,
1453 1456 'last_item': self.last_item,
1454 1457 'item_count': self.item_count,
1455 1458 'link_first': self.page > self.first_page and \
1456 1459 self._pagerlink(self.first_page, symbol_first) or '',
1457 1460 'link_last': self.page < self.last_page and \
1458 1461 self._pagerlink(self.last_page, symbol_last) or '',
1459 1462 'link_previous': self.previous_page and \
1460 1463 self._pagerlink(self.previous_page, symbol_previous) \
1461 1464 or HTML.span(symbol_previous, class_="pg-previous disabled"),
1462 1465 'link_next': self.next_page and \
1463 1466 self._pagerlink(self.next_page, symbol_next) \
1464 1467 or HTML.span(symbol_next, class_="pg-next disabled")
1465 1468 })
1466 1469
1467 1470 return literal(result)
1468 1471
1469 1472
1470 1473 #==============================================================================
1471 1474 # REPO PAGER, PAGER FOR REPOSITORY
1472 1475 #==============================================================================
1473 1476 class RepoPage(Page):
1474 1477
1475 1478 def __init__(self, collection, page=1, items_per_page=20,
1476 1479 item_count=None, url=None, **kwargs):
1477 1480
1478 1481 """Create a "RepoPage" instance. special pager for paging
1479 1482 repository
1480 1483 """
1481 1484 self._url_generator = url
1482 1485
1483 1486 # Safe the kwargs class-wide so they can be used in the pager() method
1484 1487 self.kwargs = kwargs
1485 1488
1486 1489 # Save a reference to the collection
1487 1490 self.original_collection = collection
1488 1491
1489 1492 self.collection = collection
1490 1493
1491 1494 # The self.page is the number of the current page.
1492 1495 # The first page has the number 1!
1493 1496 try:
1494 1497 self.page = int(page) # make it int() if we get it as a string
1495 1498 except (ValueError, TypeError):
1496 1499 self.page = 1
1497 1500
1498 1501 self.items_per_page = items_per_page
1499 1502
1500 1503 # Unless the user tells us how many items the collections has
1501 1504 # we calculate that ourselves.
1502 1505 if item_count is not None:
1503 1506 self.item_count = item_count
1504 1507 else:
1505 1508 self.item_count = len(self.collection)
1506 1509
1507 1510 # Compute the number of the first and last available page
1508 1511 if self.item_count > 0:
1509 1512 self.first_page = 1
1510 1513 self.page_count = int(math.ceil(float(self.item_count) /
1511 1514 self.items_per_page))
1512 1515 self.last_page = self.first_page + self.page_count - 1
1513 1516
1514 1517 # Make sure that the requested page number is the range of
1515 1518 # valid pages
1516 1519 if self.page > self.last_page:
1517 1520 self.page = self.last_page
1518 1521 elif self.page < self.first_page:
1519 1522 self.page = self.first_page
1520 1523
1521 1524 # Note: the number of items on this page can be less than
1522 1525 # items_per_page if the last page is not full
1523 1526 self.first_item = max(0, (self.item_count) - (self.page *
1524 1527 items_per_page))
1525 1528 self.last_item = ((self.item_count - 1) - items_per_page *
1526 1529 (self.page - 1))
1527 1530
1528 1531 self.items = list(self.collection[self.first_item:self.last_item + 1])
1529 1532
1530 1533 # Links to previous and next page
1531 1534 if self.page > self.first_page:
1532 1535 self.previous_page = self.page - 1
1533 1536 else:
1534 1537 self.previous_page = None
1535 1538
1536 1539 if self.page < self.last_page:
1537 1540 self.next_page = self.page + 1
1538 1541 else:
1539 1542 self.next_page = None
1540 1543
1541 1544 # No items available
1542 1545 else:
1543 1546 self.first_page = None
1544 1547 self.page_count = 0
1545 1548 self.last_page = None
1546 1549 self.first_item = None
1547 1550 self.last_item = None
1548 1551 self.previous_page = None
1549 1552 self.next_page = None
1550 1553 self.items = []
1551 1554
1552 1555 # This is a subclass of the 'list' type. Initialise the list now.
1553 1556 list.__init__(self, reversed(self.items))
1554 1557
1555 1558
1556 1559 def breadcrumb_repo_link(repo):
1557 1560 """
1558 1561 Makes a breadcrumbs path link to repo
1559 1562
1560 1563 ex::
1561 1564 group >> subgroup >> repo
1562 1565
1563 1566 :param repo: a Repository instance
1564 1567 """
1565 1568
1566 1569 path = [
1567 1570 link_to(group.name, route_path('repo_group_home', repo_group_name=group.group_name))
1568 1571 for group in repo.groups_with_parents
1569 1572 ] + [
1570 1573 link_to(repo.just_name, route_path('repo_summary', repo_name=repo.repo_name))
1571 1574 ]
1572 1575
1573 1576 return literal(' &raquo; '.join(path))
1574 1577
1575 1578
1576 1579 def format_byte_size_binary(file_size):
1577 1580 """
1578 1581 Formats file/folder sizes to standard.
1579 1582 """
1580 1583 if file_size is None:
1581 1584 file_size = 0
1582 1585
1583 1586 formatted_size = format_byte_size(file_size, binary=True)
1584 1587 return formatted_size
1585 1588
1586 1589
1587 1590 def urlify_text(text_, safe=True):
1588 1591 """
1589 1592 Extrac urls from text and make html links out of them
1590 1593
1591 1594 :param text_:
1592 1595 """
1593 1596
1594 1597 url_pat = re.compile(r'''(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@#.&+]'''
1595 1598 '''|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)''')
1596 1599
1597 1600 def url_func(match_obj):
1598 1601 url_full = match_obj.groups()[0]
1599 1602 return '<a href="%(url)s">%(url)s</a>' % ({'url': url_full})
1600 1603 _newtext = url_pat.sub(url_func, text_)
1601 1604 if safe:
1602 1605 return literal(_newtext)
1603 1606 return _newtext
1604 1607
1605 1608
1606 1609 def urlify_commits(text_, repository):
1607 1610 """
1608 1611 Extract commit ids from text and make link from them
1609 1612
1610 1613 :param text_:
1611 1614 :param repository: repo name to build the URL with
1612 1615 """
1613 1616
1614 1617 URL_PAT = re.compile(r'(^|\s)([0-9a-fA-F]{12,40})($|\s)')
1615 1618
1616 1619 def url_func(match_obj):
1617 1620 commit_id = match_obj.groups()[1]
1618 1621 pref = match_obj.groups()[0]
1619 1622 suf = match_obj.groups()[2]
1620 1623
1621 1624 tmpl = (
1622 1625 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1623 1626 '%(commit_id)s</a>%(suf)s'
1624 1627 )
1625 1628 return tmpl % {
1626 1629 'pref': pref,
1627 1630 'cls': 'revision-link',
1628 1631 'url': route_url('repo_commit', repo_name=repository,
1629 1632 commit_id=commit_id),
1630 1633 'commit_id': commit_id,
1631 1634 'suf': suf
1632 1635 }
1633 1636
1634 1637 newtext = URL_PAT.sub(url_func, text_)
1635 1638
1636 1639 return newtext
1637 1640
1638 1641
1639 1642 def _process_url_func(match_obj, repo_name, uid, entry,
1640 1643 return_raw_data=False, link_format='html'):
1641 1644 pref = ''
1642 1645 if match_obj.group().startswith(' '):
1643 1646 pref = ' '
1644 1647
1645 1648 issue_id = ''.join(match_obj.groups())
1646 1649
1647 1650 if link_format == 'html':
1648 1651 tmpl = (
1649 1652 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1650 1653 '%(issue-prefix)s%(id-repr)s'
1651 1654 '</a>')
1652 1655 elif link_format == 'rst':
1653 1656 tmpl = '`%(issue-prefix)s%(id-repr)s <%(url)s>`_'
1654 1657 elif link_format == 'markdown':
1655 1658 tmpl = '[%(issue-prefix)s%(id-repr)s](%(url)s)'
1656 1659 else:
1657 1660 raise ValueError('Bad link_format:{}'.format(link_format))
1658 1661
1659 1662 (repo_name_cleaned,
1660 1663 parent_group_name) = RepoGroupModel().\
1661 1664 _get_group_name_and_parent(repo_name)
1662 1665
1663 1666 # variables replacement
1664 1667 named_vars = {
1665 1668 'id': issue_id,
1666 1669 'repo': repo_name,
1667 1670 'repo_name': repo_name_cleaned,
1668 1671 'group_name': parent_group_name
1669 1672 }
1670 1673 # named regex variables
1671 1674 named_vars.update(match_obj.groupdict())
1672 1675 _url = string.Template(entry['url']).safe_substitute(**named_vars)
1673 1676
1674 1677 data = {
1675 1678 'pref': pref,
1676 1679 'cls': 'issue-tracker-link',
1677 1680 'url': _url,
1678 1681 'id-repr': issue_id,
1679 1682 'issue-prefix': entry['pref'],
1680 1683 'serv': entry['url'],
1681 1684 }
1682 1685 if return_raw_data:
1683 1686 return {
1684 1687 'id': issue_id,
1685 1688 'url': _url
1686 1689 }
1687 1690 return tmpl % data
1688 1691
1689 1692
1690 1693 def get_active_pattern_entries(repo_name):
1691 1694 repo = None
1692 1695 if repo_name:
1693 1696 # Retrieving repo_name to avoid invalid repo_name to explode on
1694 1697 # IssueTrackerSettingsModel but still passing invalid name further down
1695 1698 repo = Repository.get_by_repo_name(repo_name, cache=True)
1696 1699
1697 1700 settings_model = IssueTrackerSettingsModel(repo=repo)
1698 1701 active_entries = settings_model.get_settings(cache=True)
1699 1702 return active_entries
1700 1703
1701 1704
1702 1705 def process_patterns(text_string, repo_name, link_format='html',
1703 1706 active_entries=None):
1704 1707
1705 1708 allowed_formats = ['html', 'rst', 'markdown']
1706 1709 if link_format not in allowed_formats:
1707 1710 raise ValueError('Link format can be only one of:{} got {}'.format(
1708 1711 allowed_formats, link_format))
1709 1712
1710 1713 active_entries = active_entries or get_active_pattern_entries(repo_name)
1711 1714 issues_data = []
1712 1715 newtext = text_string
1713 1716
1714 1717 for uid, entry in active_entries.items():
1715 1718 log.debug('found issue tracker entry with uid %s', uid)
1716 1719
1717 1720 if not (entry['pat'] and entry['url']):
1718 1721 log.debug('skipping due to missing data')
1719 1722 continue
1720 1723
1721 1724 log.debug('issue tracker entry: uid: `%s` PAT:%s URL:%s PREFIX:%s',
1722 1725 uid, entry['pat'], entry['url'], entry['pref'])
1723 1726
1724 1727 try:
1725 1728 pattern = re.compile(r'%s' % entry['pat'])
1726 1729 except re.error:
1727 1730 log.exception(
1728 1731 'issue tracker pattern: `%s` failed to compile',
1729 1732 entry['pat'])
1730 1733 continue
1731 1734
1732 1735 data_func = partial(
1733 1736 _process_url_func, repo_name=repo_name, entry=entry, uid=uid,
1734 1737 return_raw_data=True)
1735 1738
1736 1739 for match_obj in pattern.finditer(text_string):
1737 1740 issues_data.append(data_func(match_obj))
1738 1741
1739 1742 url_func = partial(
1740 1743 _process_url_func, repo_name=repo_name, entry=entry, uid=uid,
1741 1744 link_format=link_format)
1742 1745
1743 1746 newtext = pattern.sub(url_func, newtext)
1744 1747 log.debug('processed prefix:uid `%s`', uid)
1745 1748
1746 1749 return newtext, issues_data
1747 1750
1748 1751
1749 1752 def urlify_commit_message(commit_text, repository=None,
1750 1753 active_pattern_entries=None):
1751 1754 """
1752 1755 Parses given text message and makes proper links.
1753 1756 issues are linked to given issue-server, and rest is a commit link
1754 1757
1755 1758 :param commit_text:
1756 1759 :param repository:
1757 1760 """
1758 1761 def escaper(string):
1759 1762 return string.replace('<', '&lt;').replace('>', '&gt;')
1760 1763
1761 1764 newtext = escaper(commit_text)
1762 1765
1763 1766 # extract http/https links and make them real urls
1764 1767 newtext = urlify_text(newtext, safe=False)
1765 1768
1766 1769 # urlify commits - extract commit ids and make link out of them, if we have
1767 1770 # the scope of repository present.
1768 1771 if repository:
1769 1772 newtext = urlify_commits(newtext, repository)
1770 1773
1771 1774 # process issue tracker patterns
1772 1775 newtext, issues = process_patterns(newtext, repository or '',
1773 1776 active_entries=active_pattern_entries)
1774 1777
1775 1778 return literal(newtext)
1776 1779
1777 1780
1778 1781 def render_binary(repo_name, file_obj):
1779 1782 """
1780 1783 Choose how to render a binary file
1781 1784 """
1782 1785
1783 1786 filename = file_obj.name
1784 1787
1785 1788 # images
1786 1789 for ext in ['*.png', '*.jpg', '*.ico', '*.gif']:
1787 1790 if fnmatch.fnmatch(filename, pat=ext):
1788 1791 alt = escape(filename)
1789 1792 src = route_path(
1790 1793 'repo_file_raw', repo_name=repo_name,
1791 1794 commit_id=file_obj.commit.raw_id,
1792 1795 f_path=file_obj.path)
1793 1796 return literal(
1794 1797 '<img class="rendered-binary" alt="{}" src="{}">'.format(alt, src))
1795 1798
1796 1799
1797 1800 def renderer_from_filename(filename, exclude=None):
1798 1801 """
1799 1802 choose a renderer based on filename, this works only for text based files
1800 1803 """
1801 1804
1802 1805 # ipython
1803 1806 for ext in ['*.ipynb']:
1804 1807 if fnmatch.fnmatch(filename, pat=ext):
1805 1808 return 'jupyter'
1806 1809
1807 1810 is_markup = MarkupRenderer.renderer_from_filename(filename, exclude=exclude)
1808 1811 if is_markup:
1809 1812 return is_markup
1810 1813 return None
1811 1814
1812 1815
1813 1816 def render(source, renderer='rst', mentions=False, relative_urls=None,
1814 1817 repo_name=None):
1815 1818
1816 1819 def maybe_convert_relative_links(html_source):
1817 1820 if relative_urls:
1818 1821 return relative_links(html_source, relative_urls)
1819 1822 return html_source
1820 1823
1821 1824 if renderer == 'plain':
1822 1825 return literal(
1823 1826 MarkupRenderer.plain(source, leading_newline=False))
1824 1827
1825 1828 elif renderer == 'rst':
1826 1829 if repo_name:
1827 1830 # process patterns on comments if we pass in repo name
1828 1831 source, issues = process_patterns(
1829 1832 source, repo_name, link_format='rst')
1830 1833
1831 1834 return literal(
1832 1835 '<div class="rst-block">%s</div>' %
1833 1836 maybe_convert_relative_links(
1834 1837 MarkupRenderer.rst(source, mentions=mentions)))
1835 1838
1836 1839 elif renderer == 'markdown':
1837 1840 if repo_name:
1838 1841 # process patterns on comments if we pass in repo name
1839 1842 source, issues = process_patterns(
1840 1843 source, repo_name, link_format='markdown')
1841 1844
1842 1845 return literal(
1843 1846 '<div class="markdown-block">%s</div>' %
1844 1847 maybe_convert_relative_links(
1845 1848 MarkupRenderer.markdown(source, flavored=True,
1846 1849 mentions=mentions)))
1847 1850
1848 1851 elif renderer == 'jupyter':
1849 1852 return literal(
1850 1853 '<div class="ipynb">%s</div>' %
1851 1854 maybe_convert_relative_links(
1852 1855 MarkupRenderer.jupyter(source)))
1853 1856
1854 1857 # None means just show the file-source
1855 1858 return None
1856 1859
1857 1860
1858 1861 def commit_status(repo, commit_id):
1859 1862 return ChangesetStatusModel().get_status(repo, commit_id)
1860 1863
1861 1864
1862 1865 def commit_status_lbl(commit_status):
1863 1866 return dict(ChangesetStatus.STATUSES).get(commit_status)
1864 1867
1865 1868
1866 1869 def commit_time(repo_name, commit_id):
1867 1870 repo = Repository.get_by_repo_name(repo_name)
1868 1871 commit = repo.get_commit(commit_id=commit_id)
1869 1872 return commit.date
1870 1873
1871 1874
1872 1875 def get_permission_name(key):
1873 1876 return dict(Permission.PERMS).get(key)
1874 1877
1875 1878
1876 1879 def journal_filter_help(request):
1877 1880 _ = request.translate
1878 1881 from rhodecode.lib.audit_logger import ACTIONS
1879 1882 actions = '\n'.join(textwrap.wrap(', '.join(sorted(ACTIONS.keys())), 80))
1880 1883
1881 1884 return _(
1882 1885 'Example filter terms:\n' +
1883 1886 ' repository:vcs\n' +
1884 1887 ' username:marcin\n' +
1885 1888 ' username:(NOT marcin)\n' +
1886 1889 ' action:*push*\n' +
1887 1890 ' ip:127.0.0.1\n' +
1888 1891 ' date:20120101\n' +
1889 1892 ' date:[20120101100000 TO 20120102]\n' +
1890 1893 '\n' +
1891 1894 'Actions: {actions}\n' +
1892 1895 '\n' +
1893 1896 'Generate wildcards using \'*\' character:\n' +
1894 1897 ' "repository:vcs*" - search everything starting with \'vcs\'\n' +
1895 1898 ' "repository:*vcs*" - search for repository containing \'vcs\'\n' +
1896 1899 '\n' +
1897 1900 'Optional AND / OR operators in queries\n' +
1898 1901 ' "repository:vcs OR repository:test"\n' +
1899 1902 ' "username:test AND repository:test*"\n'
1900 1903 ).format(actions=actions)
1901 1904
1902 1905
1903 1906 def search_filter_help(searcher, request):
1904 1907 _ = request.translate
1905 1908
1906 1909 terms = ''
1907 1910 return _(
1908 1911 'Example filter terms for `{searcher}` search:\n' +
1909 1912 '{terms}\n' +
1910 1913 'Generate wildcards using \'*\' character:\n' +
1911 1914 ' "repo_name:vcs*" - search everything starting with \'vcs\'\n' +
1912 1915 ' "repo_name:*vcs*" - search for repository containing \'vcs\'\n' +
1913 1916 '\n' +
1914 1917 'Optional AND / OR operators in queries\n' +
1915 1918 ' "repo_name:vcs OR repo_name:test"\n' +
1916 1919 ' "owner:test AND repo_name:test*"\n' +
1917 1920 'More: {search_doc}'
1918 1921 ).format(searcher=searcher.name,
1919 1922 terms=terms, search_doc=searcher.query_lang_doc)
1920 1923
1921 1924
1922 1925 def not_mapped_error(repo_name):
1923 1926 from rhodecode.translation import _
1924 1927 flash(_('%s repository is not mapped to db perhaps'
1925 1928 ' it was created or renamed from the filesystem'
1926 1929 ' please run the application again'
1927 1930 ' in order to rescan repositories') % repo_name, category='error')
1928 1931
1929 1932
1930 1933 def ip_range(ip_addr):
1931 1934 from rhodecode.model.db import UserIpMap
1932 1935 s, e = UserIpMap._get_ip_range(ip_addr)
1933 1936 return '%s - %s' % (s, e)
1934 1937
1935 1938
1936 1939 def form(url, method='post', needs_csrf_token=True, **attrs):
1937 1940 """Wrapper around webhelpers.tags.form to prevent CSRF attacks."""
1938 1941 if method.lower() != 'get' and needs_csrf_token:
1939 1942 raise Exception(
1940 1943 'Forms to POST/PUT/DELETE endpoints should have (in general) a ' +
1941 1944 'CSRF token. If the endpoint does not require such token you can ' +
1942 1945 'explicitly set the parameter needs_csrf_token to false.')
1943 1946
1944 1947 return wh_form(url, method=method, **attrs)
1945 1948
1946 1949
1947 1950 def secure_form(form_url, method="POST", multipart=False, **attrs):
1948 1951 """Start a form tag that points the action to an url. This
1949 1952 form tag will also include the hidden field containing
1950 1953 the auth token.
1951 1954
1952 1955 The url options should be given either as a string, or as a
1953 1956 ``url()`` function. The method for the form defaults to POST.
1954 1957
1955 1958 Options:
1956 1959
1957 1960 ``multipart``
1958 1961 If set to True, the enctype is set to "multipart/form-data".
1959 1962 ``method``
1960 1963 The method to use when submitting the form, usually either
1961 1964 "GET" or "POST". If "PUT", "DELETE", or another verb is used, a
1962 1965 hidden input with name _method is added to simulate the verb
1963 1966 over POST.
1964 1967
1965 1968 """
1966 1969 from webhelpers.pylonslib.secure_form import insecure_form
1967 1970
1968 1971 if 'request' in attrs:
1969 1972 session = attrs['request'].session
1970 1973 del attrs['request']
1971 1974 else:
1972 1975 raise ValueError(
1973 1976 'Calling this form requires request= to be passed as argument')
1974 1977
1975 1978 form = insecure_form(form_url, method, multipart, **attrs)
1976 1979 token = literal(
1977 1980 '<input type="hidden" id="{}" name="{}" value="{}">'.format(
1978 1981 csrf_token_key, csrf_token_key, get_csrf_token(session)))
1979 1982
1980 1983 return literal("%s\n%s" % (form, token))
1981 1984
1982 1985
1983 1986 def dropdownmenu(name, selected, options, enable_filter=False, **attrs):
1984 1987 select_html = select(name, selected, options, **attrs)
1985 1988 select2 = """
1986 1989 <script>
1987 1990 $(document).ready(function() {
1988 1991 $('#%s').select2({
1989 1992 containerCssClass: 'drop-menu',
1990 1993 dropdownCssClass: 'drop-menu-dropdown',
1991 1994 dropdownAutoWidth: true%s
1992 1995 });
1993 1996 });
1994 1997 </script>
1995 1998 """
1996 1999 filter_option = """,
1997 2000 minimumResultsForSearch: -1
1998 2001 """
1999 2002 input_id = attrs.get('id') or name
2000 2003 filter_enabled = "" if enable_filter else filter_option
2001 2004 select_script = literal(select2 % (input_id, filter_enabled))
2002 2005
2003 2006 return literal(select_html+select_script)
2004 2007
2005 2008
2006 2009 def get_visual_attr(tmpl_context_var, attr_name):
2007 2010 """
2008 2011 A safe way to get a variable from visual variable of template context
2009 2012
2010 2013 :param tmpl_context_var: instance of tmpl_context, usually present as `c`
2011 2014 :param attr_name: name of the attribute we fetch from the c.visual
2012 2015 """
2013 2016 visual = getattr(tmpl_context_var, 'visual', None)
2014 2017 if not visual:
2015 2018 return
2016 2019 else:
2017 2020 return getattr(visual, attr_name, None)
2018 2021
2019 2022
2020 2023 def get_last_path_part(file_node):
2021 2024 if not file_node.path:
2022 2025 return u''
2023 2026
2024 2027 path = safe_unicode(file_node.path.split('/')[-1])
2025 2028 return u'../' + path
2026 2029
2027 2030
2028 2031 def route_url(*args, **kwargs):
2029 2032 """
2030 2033 Wrapper around pyramids `route_url` (fully qualified url) function.
2031 2034 """
2032 2035 req = get_current_request()
2033 2036 return req.route_url(*args, **kwargs)
2034 2037
2035 2038
2036 2039 def route_path(*args, **kwargs):
2037 2040 """
2038 2041 Wrapper around pyramids `route_path` function.
2039 2042 """
2040 2043 req = get_current_request()
2041 2044 return req.route_path(*args, **kwargs)
2042 2045
2043 2046
2044 2047 def route_path_or_none(*args, **kwargs):
2045 2048 try:
2046 2049 return route_path(*args, **kwargs)
2047 2050 except KeyError:
2048 2051 return None
2049 2052
2050 2053
2051 2054 def current_route_path(request, **kw):
2052 2055 new_args = request.GET.mixed()
2053 2056 new_args.update(kw)
2054 2057 return request.current_route_path(_query=new_args)
2055 2058
2056 2059
2057 2060 def api_call_example(method, args):
2058 2061 """
2059 2062 Generates an API call example via CURL
2060 2063 """
2061 2064 args_json = json.dumps(OrderedDict([
2062 2065 ('id', 1),
2063 2066 ('auth_token', 'SECRET'),
2064 2067 ('method', method),
2065 2068 ('args', args)
2066 2069 ]))
2067 2070 return literal(
2068 2071 "curl {api_url} -X POST -H 'content-type:text/plain' --data-binary '{data}'"
2069 2072 "<br/><br/>SECRET can be found in <a href=\"{token_url}\">auth-tokens</a> page, "
2070 2073 "and needs to be of `api calls` role."
2071 2074 .format(
2072 2075 api_url=route_url('apiv2'),
2073 2076 token_url=route_url('my_account_auth_tokens'),
2074 2077 data=args_json))
2075 2078
2076 2079
2077 2080 def notification_description(notification, request):
2078 2081 """
2079 2082 Generate notification human readable description based on notification type
2080 2083 """
2081 2084 from rhodecode.model.notification import NotificationModel
2082 2085 return NotificationModel().make_description(
2083 2086 notification, translate=request.translate)
2084 2087
2085 2088
2086 2089 def go_import_header(request, db_repo=None):
2087 2090 """
2088 2091 Creates a header for go-import functionality in Go Lang
2089 2092 """
2090 2093
2091 2094 if not db_repo:
2092 2095 return
2093 2096 if 'go-get' not in request.GET:
2094 2097 return
2095 2098
2096 2099 clone_url = db_repo.clone_url()
2097 2100 prefix = re.split(r'^https?:\/\/', clone_url)[-1]
2098 2101 # we have a repo and go-get flag,
2099 2102 return literal('<meta name="go-import" content="{} {} {}">'.format(
2100 2103 prefix, db_repo.repo_type, clone_url))
2101 2104
2102 2105
2103 2106 def reviewer_as_json(*args, **kwargs):
2104 2107 from rhodecode.apps.repository.utils import reviewer_as_json as _reviewer_as_json
2105 2108 return _reviewer_as_json(*args, **kwargs)
@@ -1,114 +1,114 b''
1 1 <!DOCTYPE html>
2 2 <html xmlns="http://www.w3.org/1999/xhtml">
3 3 <head>
4 4 <title>Error - 502 Bad Gateway</title>
5 5 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
6 6 <meta name="robots" content="index, nofollow"/>
7 7 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
8 8 <style>
9 9 * {
10 10 box-sizing: border-box;
11 11 }
12 12 body {
13 13 background:#eeeeee;
14 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 16 margin: 0 auto;
17 17 max-width: 1000px;
18 18 letter-spacing: .02em;
19 19 font-size: 13px;
20 20 line-height: 1.41em;
21 21 }
22 22 h1 {
23 23 padding: 20px 0;
24 24 font-size: 1.54em;
25 25 }
26 26 ul {
27 27 padding-left: 10px;
28 28 }
29 29 li {
30 30 list-style-type: none;
31 31 }
32 32 li:before {
33 33 content: "\2014\00A0";
34 34 }
35 35 .error_message {
36 36 font-weight: normal;
37 37 }
38 38 .logo-container {
39 39 float: left;
40 40 width: 150px;
41 41 text-align: center;
42 42 }
43 43 a {
44 44 color: #427cc9;
45 45 text-decoration: none;
46 46 outline: none;
47 47 cursor: pointer;
48 48 }
49 49 body {
50 50 padding: 10px;
51 51 padding-top: 10%;
52 52
53 53 }
54 54 .inner-column {
55 55 padding: 10px 30px;
56 56 width: 33%;
57 57 float: left;
58 58 border-right: 1px solid #dbd9da;
59 59
60 60 }
61 61 .inner-column:last-child {
62 62 border: none;
63 63 }
64 64 .side {
65 65 min-height: 220px;
66 66 width: 150px;
67 67 float: left;
68 68 text-align: center;
69 69 border-right: 1px solid #ddd;
70 70 }
71 71 .logo {
72 72 width: 120px;
73 73 height: 150px;
74 74 }
75 75 .main {
76 76 padding-left: 170px;
77 77 }
78 78 @media (max-width: 979px) {
79 79 .inner-column {
80 80 width: 100%;
81 81 }
82 82 }
83 83 </style>
84 84
85 85 </head>
86 86 <body>
87 87 <div class="side">
88 88 <img class="logo" src="data:image/png;base64,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">
89 89 </div>
90 90 <div class="main">
91 91 <h1>
92 92 502 Bad Gateway | <span class="error_message">Backend server is unreachable</span>
93 93 </h1>
94 94 <div class="inner-column">
95 95 <h4>Possible Causes</h4>
96 96 <ul>
97 97 <li>The server is being restarted.</li>
98 98 <li>The server is overloaded.</li>
99 99 <li>The link may be incorrect.</li>
100 100 </ul>
101 101 </div>
102 102 <div class="inner-column">
103 103 <h4>Support</h4>
104 104 <p>For support, go to <a href="https://rhodecode.com/help/" target="_blank">Support</a>.
105 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 106 </p>
107 107 </div>
108 108 <div class="inner-column">
109 109 <h4>Documentation</h4>
110 110 <p>For more information, see <a href="https://rhodecode.com/r1/enterprise/docs/">docs.rhodecode.com</a>.</p>
111 111 </div>
112 112 </div>
113 113 </body>
114 114 </html>
@@ -1,1245 +1,1247 b''
1 1 // Default styles
2 2
3 3 .diff-collapse {
4 4 margin: @padding 0;
5 5 text-align: right;
6 6 }
7 7
8 8 .diff-container {
9 9 margin-bottom: @space;
10 10
11 11 .diffblock {
12 12 margin-bottom: @space;
13 13 }
14 14
15 15 &.hidden {
16 16 display: none;
17 17 overflow: hidden;
18 18 }
19 19 }
20 20
21 21
22 22 div.diffblock .sidebyside {
23 23 background: #ffffff;
24 24 }
25 25
26 26 div.diffblock {
27 27 overflow-x: auto;
28 28 overflow-y: hidden;
29 29 clear: both;
30 30 padding: 0px;
31 31 background: @grey6;
32 32 border: @border-thickness solid @grey5;
33 33 -webkit-border-radius: @border-radius @border-radius 0px 0px;
34 34 border-radius: @border-radius @border-radius 0px 0px;
35 35
36 36
37 37 .comments-number {
38 38 float: right;
39 39 }
40 40
41 41 // BEGIN CODE-HEADER STYLES
42 42
43 43 .code-header {
44 44 background: @grey6;
45 45 padding: 10px 0 10px 0;
46 46 height: auto;
47 47 width: 100%;
48 48
49 49 .hash {
50 50 float: left;
51 51 padding: 2px 0 0 2px;
52 52 }
53 53
54 54 .date {
55 55 float: left;
56 56 text-transform: uppercase;
57 57 padding: 4px 0px 0px 2px;
58 58 }
59 59
60 60 div {
61 61 margin-left: 4px;
62 62 }
63 63
64 64 div.compare_header {
65 65 min-height: 40px;
66 66 margin: 0;
67 67 padding: 0 @padding;
68 68
69 69 .drop-menu {
70 70 float:left;
71 71 display: block;
72 72 margin:0 0 @padding 0;
73 73 }
74 74
75 75 .compare-label {
76 76 float: left;
77 77 clear: both;
78 78 display: inline-block;
79 79 min-width: 5em;
80 80 margin: 0;
81 81 padding: @button-padding @button-padding @button-padding 0;
82 82 font-family: @text-semibold;
83 83 }
84 84
85 85 .compare-buttons {
86 86 float: left;
87 87 margin: 0;
88 88 padding: 0 0 @padding;
89 89
90 90 .btn {
91 91 margin: 0 @padding 0 0;
92 92 }
93 93 }
94 94 }
95 95
96 96 }
97 97
98 98 .parents {
99 99 float: left;
100 100 width: 100px;
101 101 font-weight: 400;
102 102 vertical-align: middle;
103 103 padding: 0px 2px 0px 2px;
104 104 background-color: @grey6;
105 105
106 106 #parent_link {
107 107 margin: 00px 2px;
108 108
109 109 &.double {
110 110 margin: 0px 2px;
111 111 }
112 112
113 113 &.disabled{
114 114 margin-right: @padding;
115 115 }
116 116 }
117 117 }
118 118
119 119 .children {
120 120 float: right;
121 121 width: 100px;
122 122 font-weight: 400;
123 123 vertical-align: middle;
124 124 text-align: right;
125 125 padding: 0px 2px 0px 2px;
126 126 background-color: @grey6;
127 127
128 128 #child_link {
129 129 margin: 0px 2px;
130 130
131 131 &.double {
132 132 margin: 0px 2px;
133 133 }
134 134
135 135 &.disabled{
136 136 margin-right: @padding;
137 137 }
138 138 }
139 139 }
140 140
141 141 .changeset_header {
142 142 height: 16px;
143 143
144 144 & > div{
145 145 margin-right: @padding;
146 146 }
147 147 }
148 148
149 149 .changeset_file {
150 150 text-align: left;
151 151 float: left;
152 152 padding: 0;
153 153
154 154 a{
155 155 display: inline-block;
156 156 margin-right: 0.5em;
157 157 }
158 158
159 159 #selected_mode{
160 160 margin-left: 0;
161 161 }
162 162 }
163 163
164 164 .diff-menu-wrapper {
165 165 float: left;
166 166 }
167 167
168 168 .diff-menu {
169 169 position: absolute;
170 170 background: none repeat scroll 0 0 #FFFFFF;
171 171 border-color: #003367 @grey3 @grey3;
172 172 border-right: 1px solid @grey3;
173 173 border-style: solid solid solid;
174 174 border-width: @border-thickness;
175 175 box-shadow: 2px 8px 4px rgba(0, 0, 0, 0.2);
176 176 margin-top: 5px;
177 177 margin-left: 1px;
178 178 }
179 179
180 180 .diff-actions, .editor-actions {
181 181 float: left;
182 182
183 183 input{
184 184 margin: 0 0.5em 0 0;
185 185 }
186 186 }
187 187
188 188 // END CODE-HEADER STYLES
189 189
190 190 // BEGIN CODE-BODY STYLES
191 191
192 192 .code-body {
193 193 padding: 0;
194 194 background-color: #ffffff;
195 195 position: relative;
196 196 max-width: none;
197 197 box-sizing: border-box;
198 198 // TODO: johbo: Parent has overflow: auto, this forces the child here
199 199 // to have the intended size and to scroll. Should be simplified.
200 200 width: 100%;
201 201 overflow-x: auto;
202 202 }
203 203
204 204 pre.raw {
205 205 background: white;
206 206 color: @grey1;
207 207 }
208 208 // END CODE-BODY STYLES
209 209
210 210 }
211 211
212 212
213 213 table.code-difftable {
214 214 border-collapse: collapse;
215 215 width: 99%;
216 216 border-radius: 0px !important;
217 217
218 218 td {
219 219 padding: 0 !important;
220 220 background: none !important;
221 221 border: 0 !important;
222 222 }
223 223
224 224 .context {
225 225 background: none repeat scroll 0 0 #DDE7EF;
226 226 }
227 227
228 228 .add {
229 229 background: none repeat scroll 0 0 #DDFFDD;
230 230
231 231 ins {
232 232 background: none repeat scroll 0 0 #AAFFAA;
233 233 text-decoration: none;
234 234 }
235 235 }
236 236
237 237 .del {
238 238 background: none repeat scroll 0 0 #FFDDDD;
239 239
240 240 del {
241 241 background: none repeat scroll 0 0 #FFAAAA;
242 242 text-decoration: none;
243 243 }
244 244 }
245 245
246 246 /** LINE NUMBERS **/
247 247 .lineno {
248 248 padding-left: 2px !important;
249 249 padding-right: 2px;
250 250 text-align: right;
251 251 width: 32px;
252 252 -moz-user-select: none;
253 253 -webkit-user-select: none;
254 254 border-right: @border-thickness solid @grey5 !important;
255 255 border-left: 0px solid #CCC !important;
256 256 border-top: 0px solid #CCC !important;
257 257 border-bottom: none !important;
258 258
259 259 a {
260 260 &:extend(pre);
261 261 text-align: right;
262 262 padding-right: 2px;
263 263 cursor: pointer;
264 264 display: block;
265 265 width: 32px;
266 266 }
267 267 }
268 268
269 269 .context {
270 270 cursor: auto;
271 271 &:extend(pre);
272 272 }
273 273
274 274 .lineno-inline {
275 275 background: none repeat scroll 0 0 #FFF !important;
276 276 padding-left: 2px;
277 277 padding-right: 2px;
278 278 text-align: right;
279 279 width: 30px;
280 280 -moz-user-select: none;
281 281 -webkit-user-select: none;
282 282 }
283 283
284 284 /** CODE **/
285 285 .code {
286 286 display: block;
287 287 width: 100%;
288 288
289 289 td {
290 290 margin: 0;
291 291 padding: 0;
292 292 }
293 293
294 294 pre {
295 295 margin: 0;
296 296 padding: 0;
297 297 margin-left: .5em;
298 298 }
299 299 }
300 300 }
301 301
302 302
303 303 // Comments
304 304
305 305 div.comment:target {
306 306 border-left: 6px solid @comment-highlight-color !important;
307 307 padding-left: 3px;
308 308 margin-left: -9px;
309 309 }
310 310
311 311 //TODO: anderson: can't get an absolute number out of anything, so had to put the
312 312 //current values that might change. But to make it clear I put as a calculation
313 313 @comment-max-width: 1065px;
314 314 @pr-extra-margin: 34px;
315 315 @pr-border-spacing: 4px;
316 316 @pr-comment-width: @comment-max-width - @pr-extra-margin - @pr-border-spacing;
317 317
318 318 // Pull Request
319 319 .cs_files .code-difftable {
320 320 border: @border-thickness solid @grey5; //borders only on PRs
321 321
322 322 .comment-inline-form,
323 323 div.comment {
324 324 width: @pr-comment-width;
325 325 }
326 326 }
327 327
328 328 // Changeset
329 329 .code-difftable {
330 330 .comment-inline-form,
331 331 div.comment {
332 332 width: @comment-max-width;
333 333 }
334 334 }
335 335
336 336 //Style page
337 337 @style-extra-margin: @sidebar-width + (@sidebarpadding * 3) + @padding;
338 338 #style-page .code-difftable{
339 339 .comment-inline-form,
340 340 div.comment {
341 341 width: @comment-max-width - @style-extra-margin;
342 342 }
343 343 }
344 344
345 345 #context-bar > h2 {
346 346 font-size: 20px;
347 347 }
348 348
349 349 #context-bar > h2> a {
350 350 font-size: 20px;
351 351 }
352 352 // end of defaults
353 353
354 354 .file_diff_buttons {
355 355 padding: 0 0 @padding;
356 356
357 357 .drop-menu {
358 358 float: left;
359 359 margin: 0 @padding 0 0;
360 360 }
361 361 .btn {
362 362 margin: 0 @padding 0 0;
363 363 }
364 364 }
365 365
366 366 .code-body.textarea.editor {
367 367 max-width: none;
368 368 padding: 15px;
369 369 }
370 370
371 371 td.injected_diff{
372 372 max-width: 1178px;
373 373 overflow-x: auto;
374 374 overflow-y: hidden;
375 375
376 376 div.diff-container,
377 377 div.diffblock{
378 378 max-width: 100%;
379 379 }
380 380
381 381 div.code-body {
382 382 max-width: 1124px;
383 383 overflow-x: auto;
384 384 overflow-y: hidden;
385 385 padding: 0;
386 386 }
387 387 div.diffblock {
388 388 border: none;
389 389 }
390 390
391 391 &.inline-form {
392 392 width: 99%
393 393 }
394 394 }
395 395
396 396
397 397 table.code-difftable {
398 398 width: 100%;
399 399 }
400 400
401 401 /** PYGMENTS COLORING **/
402 402 div.codeblock {
403 403
404 404 // TODO: johbo: Added interim to get rid of the margin around
405 405 // Select2 widgets. This needs further cleanup.
406 406 margin-top: @padding;
407 407
408 408 overflow: auto;
409 409 padding: 0px;
410 410 border: @border-thickness solid @grey5;
411 411 background: @grey6;
412 412 .border-radius(@border-radius);
413 413
414 414 #remove_gist {
415 415 float: right;
416 416 }
417 417
418 418 .gist_url {
419 419 padding: 0px 0px 10px 0px;
420 420 }
421 421
422 422 .author {
423 423 clear: both;
424 424 vertical-align: middle;
425 425 font-family: @text-bold;
426 426 }
427 427
428 428 .btn-mini {
429 429 float: left;
430 430 margin: 0 5px 0 0;
431 431 }
432 432
433 433 .code-header {
434 434 padding: @padding;
435 435 border-bottom: @border-thickness solid @grey5;
436 436
437 437 .rc-user {
438 438 min-width: 0;
439 439 margin-right: .5em;
440 440 }
441 441
442 442 .stats {
443 443 clear: both;
444 444 margin: 0 0 @padding 0;
445 445 padding: 0;
446 446 .left {
447 447 float: left;
448 448 clear: left;
449 449 max-width: 75%;
450 450 margin: 0 0 @padding 0;
451 451
452 452 &.item {
453 453 margin-right: @padding;
454 454 &.last { border-right: none; }
455 455 }
456 456 }
457 457 .buttons { float: right; }
458 458 .author {
459 459 height: 25px; margin-left: 15px; font-weight: bold;
460 460 }
461 461 }
462 462
463 463 .commit {
464 464 margin: 5px 0 0 26px;
465 465 font-weight: normal;
466 466 white-space: pre-wrap;
467 467 }
468 468 }
469 469
470 470 .message {
471 471 position: relative;
472 472 margin: @padding;
473 473
474 474 .codeblock-label {
475 475 margin: 0 0 1em 0;
476 476 }
477 477 }
478 478
479 479 .code-body {
480 480 padding: @padding;
481 481 background-color: #ffffff;
482 482 min-width: 100%;
483 483 box-sizing: border-box;
484 484 // TODO: johbo: Parent has overflow: auto, this forces the child here
485 485 // to have the intended size and to scroll. Should be simplified.
486 486 width: 100%;
487 487 overflow-x: auto;
488 488
489 489 img.rendered-binary {
490 490 height: auto;
491 491 width: 100%;
492 492 }
493 493 }
494 494 }
495 495
496 496 .code-highlighttable,
497 497 div.codeblock {
498 498
499 499 &.readme {
500 500 background-color: white;
501 501 }
502 502
503 503 .markdown-block table {
504 504 border-collapse: collapse;
505 505
506 506 th,
507 507 td {
508 508 padding: .5em;
509 509 border: @border-thickness solid @border-default-color;
510 510 }
511 511 }
512 512
513 513 table {
514 514 border: 0px;
515 515 margin: 0;
516 516 letter-spacing: normal;
517 517
518 518
519 519 td {
520 520 border: 0px;
521 521 vertical-align: top;
522 522 }
523 523 }
524 524 }
525 525
526 526 div.codeblock .code-header .search-path { padding: 0 0 0 10px; }
527 527 div.search-code-body {
528 528 background-color: #ffffff; padding: 5px 0 5px 10px;
529 529 pre {
530 530 .match { background-color: #faffa6;}
531 531 .break { display: block; width: 100%; background-color: #DDE7EF; color: #747474; }
532 532 }
533 533 .code-highlighttable {
534 534 border-collapse: collapse;
535 535
536 536 tr:hover {
537 537 background: #fafafa;
538 538 }
539 539 td.code {
540 540 padding-left: 10px;
541 541 }
542 542 td.line {
543 543 border-right: 1px solid #ccc !important;
544 544 padding-right: 10px;
545 545 text-align: right;
546 546 font-family: "Lucida Console",Monaco,monospace;
547 547 span {
548 548 white-space: pre-wrap;
549 549 color: #666666;
550 550 }
551 551 }
552 552 }
553 553 }
554 554
555 555 div.annotatediv { margin-left: 2px; margin-right: 4px; }
556 556 .code-highlight {
557 557 margin: 0; padding: 0; border-left: @border-thickness solid @grey5;
558 558 pre, .linenodiv pre { padding: 0 5px; margin: 0; }
559 559 pre div:target {background-color: @comment-highlight-color !important;}
560 560 }
561 561
562 562 .linenos a { text-decoration: none; }
563 563
564 564 .CodeMirror-selected { background: @rchighlightblue; }
565 565 .CodeMirror-focused .CodeMirror-selected { background: @rchighlightblue; }
566 566 .CodeMirror ::selection { background: @rchighlightblue; }
567 567 .CodeMirror ::-moz-selection { background: @rchighlightblue; }
568 568
569 569 .code { display: block; border:0px !important; }
570 570 .code-highlight, /* TODO: dan: merge codehilite into code-highlight */
571 571 .codehilite {
572 572 .hll { background-color: #ffffcc }
573 573 .c { color: #408080; font-style: italic } /* Comment */
574 574 .err, .codehilite .err { border: none } /* Error */
575 575 .k { color: #008000; font-weight: bold } /* Keyword */
576 576 .o { color: #666666 } /* Operator */
577 577 .cm { color: #408080; font-style: italic } /* Comment.Multiline */
578 578 .cp { color: #BC7A00 } /* Comment.Preproc */
579 579 .c1 { color: #408080; font-style: italic } /* Comment.Single */
580 580 .cs { color: #408080; font-style: italic } /* Comment.Special */
581 581 .gd { color: #A00000 } /* Generic.Deleted */
582 582 .ge { font-style: italic } /* Generic.Emph */
583 583 .gr { color: #FF0000 } /* Generic.Error */
584 584 .gh { color: #000080; font-weight: bold } /* Generic.Heading */
585 585 .gi { color: #00A000 } /* Generic.Inserted */
586 586 .go { color: #808080 } /* Generic.Output */
587 587 .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
588 588 .gs { font-weight: bold } /* Generic.Strong */
589 589 .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
590 590 .gt { color: #0040D0 } /* Generic.Traceback */
591 591 .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
592 592 .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
593 593 .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
594 594 .kp { color: #008000 } /* Keyword.Pseudo */
595 595 .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
596 596 .kt { color: #B00040 } /* Keyword.Type */
597 597 .m { color: #666666 } /* Literal.Number */
598 598 .s { color: #BA2121 } /* Literal.String */
599 599 .na { color: #7D9029 } /* Name.Attribute */
600 600 .nb { color: #008000 } /* Name.Builtin */
601 601 .nc { color: #0000FF; font-weight: bold } /* Name.Class */
602 602 .no { color: #880000 } /* Name.Constant */
603 603 .nd { color: #AA22FF } /* Name.Decorator */
604 604 .ni { color: #999999; font-weight: bold } /* Name.Entity */
605 605 .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
606 606 .nf { color: #0000FF } /* Name.Function */
607 607 .nl { color: #A0A000 } /* Name.Label */
608 608 .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
609 609 .nt { color: #008000; font-weight: bold } /* Name.Tag */
610 610 .nv { color: #19177C } /* Name.Variable */
611 611 .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
612 612 .w { color: #bbbbbb } /* Text.Whitespace */
613 613 .mf { color: #666666 } /* Literal.Number.Float */
614 614 .mh { color: #666666 } /* Literal.Number.Hex */
615 615 .mi { color: #666666 } /* Literal.Number.Integer */
616 616 .mo { color: #666666 } /* Literal.Number.Oct */
617 617 .sb { color: #BA2121 } /* Literal.String.Backtick */
618 618 .sc { color: #BA2121 } /* Literal.String.Char */
619 619 .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
620 620 .s2 { color: #BA2121 } /* Literal.String.Double */
621 621 .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
622 622 .sh { color: #BA2121 } /* Literal.String.Heredoc */
623 623 .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
624 624 .sx { color: #008000 } /* Literal.String.Other */
625 625 .sr { color: #BB6688 } /* Literal.String.Regex */
626 626 .s1 { color: #BA2121 } /* Literal.String.Single */
627 627 .ss { color: #19177C } /* Literal.String.Symbol */
628 628 .bp { color: #008000 } /* Name.Builtin.Pseudo */
629 629 .vc { color: #19177C } /* Name.Variable.Class */
630 630 .vg { color: #19177C } /* Name.Variable.Global */
631 631 .vi { color: #19177C } /* Name.Variable.Instance */
632 632 .il { color: #666666 } /* Literal.Number.Integer.Long */
633 633 }
634 634
635 635 /* customized pre blocks for markdown/rst */
636 636 pre.literal-block, .codehilite pre{
637 637 padding: @padding;
638 638 border: 1px solid @grey6;
639 639 .border-radius(@border-radius);
640 640 background-color: @grey7;
641 641 }
642 642
643 643
644 644 /* START NEW CODE BLOCK CSS */
645 645
646 646 @cb-line-height: 18px;
647 647 @cb-line-code-padding: 10px;
648 648 @cb-text-padding: 5px;
649 649
650 650 @pill-padding: 2px 7px;
651 651 @pill-padding-small: 2px 2px 1px 2px;
652 652
653 653 input.filediff-collapse-state {
654 654 display: none;
655 655
656 656 &:checked + .filediff { /* file diff is collapsed */
657 657 .cb {
658 658 display: none
659 659 }
660 660 .filediff-collapse-indicator {
661 661 width: 0;
662 662 height: 0;
663 663 border-style: solid;
664 664 border-width: 4.5px 0 4.5px 9.3px;
665 665 border-color: transparent transparent transparent #aaa;
666 666 margin: 6px 0px;
667 667 }
668 668 .filediff-menu {
669 669 display: none;
670 670 }
671 671
672 672 }
673 673
674 674 &+ .filediff { /* file diff is expanded */
675 675 .filediff-collapse-indicator {
676 676 width: 0;
677 677 height: 0;
678 678 border-style: solid;
679 679 border-width: 9.3px 4.5px 0 4.5px;
680 680 border-color: #aaa transparent transparent transparent;
681 681 margin: 6px 0px;
682 682
683 683 }
684 684 .filediff-menu {
685 685 display: block;
686 686 }
687 687 margin: 10px 0;
688 688 &:nth-child(2) {
689 689 margin: 0;
690 690 }
691 691 }
692 692 }
693 693
694 694 .filediffs .anchor {
695 695 display: block;
696 696 height: 40px;
697 697 margin-top: -40px;
698 698 visibility: hidden;
699 699 }
700 700
701 701 .filediffs .anchor:nth-of-type(1) {
702 702 display: block;
703 703 height: 80px;
704 704 margin-top: -80px;
705 705 visibility: hidden;
706 706 }
707 707
708 708 .cs_files {
709 709 clear: both;
710 710 }
711 711
712 712 #diff-file-sticky{
713 713 will-change: min-height;
714 714 }
715 715
716 716 .sidebar__inner{
717 717 transform: translate(0, 0); /* For browsers don't support translate3d. */
718 718 transform: translate3d(0, 0, 0);
719 719 will-change: position, transform;
720 720 height: 70px;
721 721 z-index: 30;
722 722 background-color: #fff;
723 723 padding: 5px 0px;
724 724 }
725 725
726 726 .sidebar__bar {
727 727 padding: 5px 0px 0px 0px
728 728 }
729 729
730 730 .fpath-placeholder {
731 731 clear: both;
732 732 visibility: hidden
733 733 }
734 734
735 735 .is-affixed {
736 736 .sidebar_inner_shadow {
737 737 position: fixed;
738 738 top: 75px;
739 739 right: -100%;
740 740 left: -100%;
741 741 z-index: 28;
742 742 display: block;
743 743 height: 5px;
744 744 content: "";
745 745 background: linear-gradient(rgba(0, 0, 0, 0.075), rgba(0, 0, 0, 0.001)) repeat-x 0 0;
746 746 border-top: 1px solid rgba(0, 0, 0, 0.15);
747 747 }
748 748 .fpath-placeholder {
749 749 visibility: visible !important;
750 750 }
751 751 }
752 752
753 753 .diffset-menu {
754 754 margin-bottom: 20px;
755 755 }
756 756 .diffset {
757 757 margin: 20px auto;
758 758 .diffset-heading {
759 759 border: 1px solid @grey5;
760 760 margin-bottom: -1px;
761 761 // margin-top: 20px;
762 762 h2 {
763 763 margin: 0;
764 764 line-height: 38px;
765 765 padding-left: 10px;
766 766 }
767 767 .btn {
768 768 margin: 0;
769 769 }
770 770 background: @grey6;
771 771 display: block;
772 772 padding: 5px;
773 773 }
774 774 .diffset-heading-warning {
775 775 background: @alert3-inner;
776 776 border: 1px solid @alert3;
777 777 }
778 778 &.diffset-comments-disabled {
779 779 .cb-comment-box-opener, .comment-inline-form, .cb-comment-add-button {
780 780 display: none !important;
781 781 }
782 782 }
783 783 }
784 784
785 785 .filelist {
786 786 .pill {
787 787 display: block;
788 788 float: left;
789 789 padding: @pill-padding-small;
790 790 }
791 791 }
792 792
793 793 .pill {
794 794 display: block;
795 795 float: left;
796 796 padding: @pill-padding;
797 797 }
798 798
799 799 .pill-group {
800 800 .pill {
801 801 opacity: .8;
802 802 margin-right: 3px;
803 font-size: 12px;
804 font-weight: normal;
803 805
804 806 &:first-child {
805 807 border-radius: @border-radius 0 0 @border-radius;
806 808 }
807 809 &:last-child {
808 810 border-radius: 0 @border-radius @border-radius 0;
809 811 }
810 812 &:only-child {
811 813 border-radius: @border-radius;
812 814 margin-right: 0;
813 815 }
814 816 }
815 817 }
816 818
817 819 /* Main comments*/
818 820 #comments {
819 821 .comment-selected {
820 822 border-left: 6px solid @comment-highlight-color;
821 823 padding-left: 3px;
822 824 margin-left: -9px;
823 825 }
824 826 }
825 827
826 828 .filediff {
827 829 border: 1px solid @grey5;
828 830
829 831 /* START OVERRIDES */
830 832 .code-highlight {
831 833 border: none; // TODO: remove this border from the global
832 834 // .code-highlight, it doesn't belong there
833 835 }
834 836 label {
835 837 margin: 0; // TODO: remove this margin definition from global label
836 838 // it doesn't belong there - if margin on labels
837 839 // are needed for a form they should be defined
838 840 // in the form's class
839 841 }
840 842 /* END OVERRIDES */
841 843
842 844 * {
843 845 box-sizing: border-box;
844 846 }
845 847 .filediff-anchor {
846 848 visibility: hidden;
847 849 }
848 850 &:hover {
849 851 .filediff-anchor {
850 852 visibility: visible;
851 853 }
852 854 }
853 855
854 856 .filediff-collapse-indicator {
855 857 border-style: solid;
856 858 float: left;
857 859 margin: 4px 0px 0 0;
858 860 cursor: pointer;
859 861 }
860 862
861 863 .filediff-heading {
862 864 background: @grey7;
863 865 cursor: pointer;
864 866 display: block;
865 867 padding: 5px 10px;
866 868 }
867 869 .filediff-heading:after {
868 870 content: "";
869 871 display: table;
870 872 clear: both;
871 873 }
872 874 .filediff-heading:hover {
873 875 background: #e1e9f4 !important;
874 876 }
875 877
876 878 .filediff-menu {
877 879 float: right;
878 880 text-align: right;
879 881 padding: 5px 5px 5px 0px;
880 882
881 883 &> a,
882 884 &> span {
883 885 padding: 1px;
884 886 }
885 887 }
886 888
887 889 .filediff-collapse-button, .filediff-expand-button {
888 890 cursor: pointer;
889 891 }
890 892 .filediff-collapse-button {
891 893 display: inline;
892 894 }
893 895 .filediff-expand-button {
894 896 display: none;
895 897 }
896 898 .filediff-collapsed .filediff-collapse-button {
897 899 display: none;
898 900 }
899 901 .filediff-collapsed .filediff-expand-button {
900 902 display: inline;
901 903 }
902 904
903 905 /**** COMMENTS ****/
904 906
905 907 .filediff-menu {
906 908 .show-comment-button {
907 909 display: none;
908 910 }
909 911 }
910 912 &.hide-comments {
911 913 .inline-comments {
912 914 display: none;
913 915 }
914 916 .filediff-menu {
915 917 .show-comment-button {
916 918 display: inline;
917 919 }
918 920 .hide-comment-button {
919 921 display: none;
920 922 }
921 923 }
922 924 }
923 925
924 926 .hide-line-comments {
925 927 .inline-comments {
926 928 display: none;
927 929 }
928 930 }
929 931
930 932 /**** END COMMENTS ****/
931 933
932 934 }
933 935
934 936
935 937
936 938 .filediff, .filelist {
937 939 .pill {
938 940 &[op="name"] {
939 941 background: none;
940 942 opacity: 1;
941 943 color: white;
942 944 }
943 945 &[op="limited"] {
944 946 background: @grey2;
945 947 color: white;
946 948 }
947 949 &[op="binary"] {
948 950 background: @color7;
949 951 color: white;
950 952 }
951 953 &[op="modified"] {
952 954 background: @alert1;
953 955 color: white;
954 956 }
955 957 &[op="renamed"] {
956 958 background: @color4;
957 959 color: white;
958 960 }
959 961 &[op="copied"] {
960 962 background: @color4;
961 963 color: white;
962 964 }
963 965 &[op="mode"] {
964 966 background: @grey3;
965 967 color: white;
966 968 }
967 969 &[op="symlink"] {
968 970 background: @color8;
969 971 color: white;
970 972 }
971 973
972 974 &[op="added"] { /* added lines */
973 975 background: @alert1;
974 976 color: white;
975 977 }
976 978 &[op="deleted"] { /* deleted lines */
977 979 background: @alert2;
978 980 color: white;
979 981 }
980 982
981 983 &[op="created"] { /* created file */
982 984 background: @alert1;
983 985 color: white;
984 986 }
985 987 &[op="removed"] { /* deleted file */
986 988 background: @color5;
987 989 color: white;
988 990 }
989 991 }
990 992 }
991 993
992 994
993 995 .filediff-outdated {
994 996 padding: 8px 0;
995 997
996 998 .filediff-heading {
997 999 opacity: .5;
998 1000 }
999 1001 }
1000 1002
1001 1003 table.cb {
1002 1004 width: 100%;
1003 1005 border-collapse: collapse;
1004 1006
1005 1007 .cb-text {
1006 1008 padding: @cb-text-padding;
1007 1009 }
1008 1010 .cb-hunk {
1009 1011 padding: @cb-text-padding;
1010 1012 }
1011 1013 .cb-expand {
1012 1014 display: none;
1013 1015 }
1014 1016 .cb-collapse {
1015 1017 display: inline;
1016 1018 }
1017 1019 &.cb-collapsed {
1018 1020 .cb-line {
1019 1021 display: none;
1020 1022 }
1021 1023 .cb-expand {
1022 1024 display: inline;
1023 1025 }
1024 1026 .cb-collapse {
1025 1027 display: none;
1026 1028 }
1027 1029 .cb-hunk {
1028 1030 display: none;
1029 1031 }
1030 1032 }
1031 1033
1032 1034 /* intentionally general selector since .cb-line-selected must override it
1033 1035 and they both use !important since the td itself may have a random color
1034 1036 generated by annotation blocks. TLDR: if you change it, make sure
1035 1037 annotated block selection and line selection in file view still work */
1036 1038 .cb-line-fresh .cb-content {
1037 1039 background: white !important;
1038 1040 }
1039 1041 .cb-warning {
1040 1042 background: #fff4dd;
1041 1043 }
1042 1044
1043 1045 &.cb-diff-sideside {
1044 1046 td {
1045 1047 &.cb-content {
1046 1048 width: 50%;
1047 1049 }
1048 1050 }
1049 1051 }
1050 1052
1051 1053 tr {
1052 1054 &.cb-annotate {
1053 1055 border-top: 1px solid #eee;
1054 1056 }
1055 1057
1056 1058 &.cb-comment-info {
1057 1059 border-top: 1px solid #eee;
1058 1060 color: rgba(0, 0, 0, 0.3);
1059 1061 background: #edf2f9;
1060 1062
1061 1063 td {
1062 1064
1063 1065 }
1064 1066 }
1065 1067
1066 1068 &.cb-hunk {
1067 1069 font-family: @font-family-monospace;
1068 1070 color: rgba(0, 0, 0, 0.3);
1069 1071
1070 1072 td {
1071 1073 &:first-child {
1072 1074 background: #edf2f9;
1073 1075 }
1074 1076 &:last-child {
1075 1077 background: #f4f7fb;
1076 1078 }
1077 1079 }
1078 1080 }
1079 1081 }
1080 1082
1081 1083
1082 1084 td {
1083 1085 vertical-align: top;
1084 1086 padding: 0;
1085 1087
1086 1088 &.cb-content {
1087 1089 font-size: 12.35px;
1088 1090
1089 1091 &.cb-line-selected .cb-code {
1090 1092 background: @comment-highlight-color !important;
1091 1093 }
1092 1094
1093 1095 span.cb-code {
1094 1096 line-height: @cb-line-height;
1095 1097 padding-left: @cb-line-code-padding;
1096 1098 padding-right: @cb-line-code-padding;
1097 1099 display: block;
1098 1100 white-space: pre-wrap;
1099 1101 font-family: @font-family-monospace;
1100 1102 word-break: break-all;
1101 1103 .nonl {
1102 1104 color: @color5;
1103 1105 }
1104 1106 .cb-action {
1105 1107 &:before {
1106 1108 content: " ";
1107 1109 }
1108 1110 &.cb-deletion:before {
1109 1111 content: "- ";
1110 1112 }
1111 1113 &.cb-addition:before {
1112 1114 content: "+ ";
1113 1115 }
1114 1116 }
1115 1117 }
1116 1118
1117 1119 &> button.cb-comment-box-opener {
1118 1120
1119 1121 padding: 2px 2px 1px 3px;
1120 1122 margin-left: -6px;
1121 1123 margin-top: -1px;
1122 1124
1123 1125 border-radius: @border-radius;
1124 1126 position: absolute;
1125 1127 display: none;
1126 1128 }
1127 1129 .cb-comment {
1128 1130 margin-top: 10px;
1129 1131 white-space: normal;
1130 1132 }
1131 1133 }
1132 1134 &:hover {
1133 1135 button.cb-comment-box-opener {
1134 1136 display: block;
1135 1137 }
1136 1138 &+ td button.cb-comment-box-opener {
1137 1139 display: block
1138 1140 }
1139 1141 }
1140 1142
1141 1143 &.cb-data {
1142 1144 text-align: right;
1143 1145 width: 30px;
1144 1146 font-family: @font-family-monospace;
1145 1147
1146 1148 .icon-comment {
1147 1149 cursor: pointer;
1148 1150 }
1149 1151 &.cb-line-selected {
1150 1152 background: @comment-highlight-color !important;
1151 1153 }
1152 1154 &.cb-line-selected > div {
1153 1155 display: block;
1154 1156 background: @comment-highlight-color !important;
1155 1157 line-height: @cb-line-height;
1156 1158 color: rgba(0, 0, 0, 0.3);
1157 1159 }
1158 1160 }
1159 1161
1160 1162 &.cb-lineno {
1161 1163 padding: 0;
1162 1164 width: 50px;
1163 1165 color: rgba(0, 0, 0, 0.3);
1164 1166 text-align: right;
1165 1167 border-right: 1px solid #eee;
1166 1168 font-family: @font-family-monospace;
1167 1169 -webkit-user-select: none;
1168 1170 -moz-user-select: none;
1169 1171 user-select: none;
1170 1172
1171 1173 a::before {
1172 1174 content: attr(data-line-no);
1173 1175 }
1174 1176 &.cb-line-selected {
1175 1177 background: @comment-highlight-color !important;
1176 1178 }
1177 1179
1178 1180 a {
1179 1181 display: block;
1180 1182 padding-right: @cb-line-code-padding;
1181 1183 padding-left: @cb-line-code-padding;
1182 1184 line-height: @cb-line-height;
1183 1185 color: rgba(0, 0, 0, 0.3);
1184 1186 }
1185 1187 }
1186 1188
1187 1189 &.cb-empty {
1188 1190 background: @grey7;
1189 1191 }
1190 1192
1191 1193 ins {
1192 1194 color: black;
1193 1195 background: #a6f3a6;
1194 1196 text-decoration: none;
1195 1197 }
1196 1198 del {
1197 1199 color: black;
1198 1200 background: #f8cbcb;
1199 1201 text-decoration: none;
1200 1202 }
1201 1203 &.cb-addition {
1202 1204 background: #ecffec;
1203 1205
1204 1206 &.blob-lineno {
1205 1207 background: #ddffdd;
1206 1208 }
1207 1209 }
1208 1210 &.cb-deletion {
1209 1211 background: #ffecec;
1210 1212
1211 1213 &.blob-lineno {
1212 1214 background: #ffdddd;
1213 1215 }
1214 1216 }
1215 1217 &.cb-annotate-message-spacer {
1216 1218 width:8px;
1217 1219 padding: 1px 0px 0px 3px;
1218 1220 }
1219 1221 &.cb-annotate-info {
1220 1222 width: 320px;
1221 1223 min-width: 320px;
1222 1224 max-width: 320px;
1223 1225 padding: 5px 2px;
1224 1226 font-size: 13px;
1225 1227
1226 1228 .cb-annotate-message {
1227 1229 padding: 2px 0px 0px 0px;
1228 1230 white-space: pre-line;
1229 1231 overflow: hidden;
1230 1232 }
1231 1233 .rc-user {
1232 1234 float: none;
1233 1235 padding: 0 6px 0 17px;
1234 1236 min-width: unset;
1235 1237 min-height: unset;
1236 1238 }
1237 1239 }
1238 1240
1239 1241 &.cb-annotate-revision {
1240 1242 cursor: pointer;
1241 1243 text-align: right;
1242 1244 padding: 1px 3px 0px 3px;
1243 1245 }
1244 1246 }
1245 1247 }
@@ -1,2466 +1,2453 b''
1 1 //Primary CSS
2 2
3 3 //--- IMPORTS ------------------//
4 4
5 5 @import 'helpers';
6 6 @import 'mixins';
7 7 @import 'rcicons';
8 @import 'fonts';
9 8 @import 'variables';
10 9 @import 'bootstrap-variables';
11 10 @import 'form-bootstrap';
12 11 @import 'codemirror';
13 12 @import 'legacy_code_styles';
14 13 @import 'readme-box';
15 14 @import 'progress-bar';
16 15
17 16 @import 'type';
18 17 @import 'alerts';
19 18 @import 'buttons';
20 19 @import 'tags';
21 20 @import 'code-block';
22 21 @import 'examples';
23 22 @import 'login';
24 23 @import 'main-content';
25 24 @import 'select2';
26 25 @import 'comments';
27 26 @import 'panels-bootstrap';
28 27 @import 'panels';
29 28 @import 'deform';
30 29
31 30 //--- BASE ------------------//
32 31 .noscript-error {
33 32 top: 0;
34 33 left: 0;
35 34 width: 100%;
36 35 z-index: 101;
37 36 text-align: center;
38 37 font-family: @text-semibold;
39 38 font-size: 120%;
40 39 color: white;
41 40 background-color: @alert2;
42 41 padding: 5px 0 5px 0;
43 42 }
44 43
45 44 html {
46 45 display: table;
47 46 height: 100%;
48 47 width: 100%;
49 48 }
50 49
51 50 body {
52 51 display: table-cell;
53 52 width: 100%;
54 53 }
55 54
56 55 //--- LAYOUT ------------------//
57 56
58 57 .hidden{
59 58 display: none !important;
60 59 }
61 60
62 61 .box{
63 62 float: left;
64 63 width: 100%;
65 64 }
66 65
67 66 .browser-header {
68 67 clear: both;
69 68 }
70 69 .main {
71 70 clear: both;
72 71 padding:0 0 @pagepadding;
73 72 height: auto;
74 73
75 74 &:after { //clearfix
76 75 content:"";
77 76 clear:both;
78 77 width:100%;
79 78 display:block;
80 79 }
81 80 }
82 81
83 82 .action-link{
84 83 margin-left: @padding;
85 84 padding-left: @padding;
86 85 border-left: @border-thickness solid @border-default-color;
87 86 }
88 87
89 88 input + .action-link, .action-link.first{
90 89 border-left: none;
91 90 }
92 91
93 92 .action-link.last{
94 93 margin-right: @padding;
95 94 padding-right: @padding;
96 95 }
97 96
98 97 .action-link.active,
99 98 .action-link.active a{
100 99 color: @grey4;
101 100 }
102 101
103 102 .action-link.disabled {
104 103 color: @grey4;
105 104 cursor: inherit;
106 105 }
107 106
108 107 .clipboard-action {
109 108 cursor: pointer;
110 109 }
111 110
112 111 ul.simple-list{
113 112 list-style: none;
114 113 margin: 0;
115 114 padding: 0;
116 115 }
117 116
118 117 .main-content {
119 118 padding-bottom: @pagepadding;
120 119 }
121 120
122 121 .wide-mode-wrapper {
123 122 max-width:4000px !important;
124 123 }
125 124
126 125 .wrapper {
127 126 position: relative;
128 127 max-width: @wrapper-maxwidth;
129 128 margin: 0 auto;
130 129 }
131 130
132 131 #content {
133 132 clear: both;
134 133 padding: 0 @contentpadding;
135 134 }
136 135
137 136 .advanced-settings-fields{
138 137 input{
139 138 margin-left: @textmargin;
140 139 margin-right: @padding/2;
141 140 }
142 141 }
143 142
144 143 .cs_files_title {
145 144 margin: @pagepadding 0 0;
146 145 }
147 146
148 147 input.inline[type="file"] {
149 148 display: inline;
150 149 }
151 150
152 151 .error_page {
153 152 margin: 10% auto;
154 153
155 154 h1 {
156 155 color: @grey2;
157 156 }
158 157
159 158 .alert {
160 159 margin: @padding 0;
161 160 }
162 161
163 162 .error-branding {
164 163 font-family: @text-semibold;
165 164 color: @grey4;
166 165 }
167 166
168 167 .error_message {
169 168 font-family: @text-regular;
170 169 }
171 170
172 171 .sidebar {
173 172 min-height: 275px;
174 173 margin: 0;
175 174 padding: 0 0 @sidebarpadding @sidebarpadding;
176 175 border: none;
177 176 }
178 177
179 178 .main-content {
180 179 position: relative;
181 180 margin: 0 @sidebarpadding @sidebarpadding;
182 181 padding: 0 0 0 @sidebarpadding;
183 182 border-left: @border-thickness solid @grey5;
184 183
185 184 @media (max-width:767px) {
186 185 clear: both;
187 186 width: 100%;
188 187 margin: 0;
189 188 border: none;
190 189 }
191 190 }
192 191
193 192 .inner-column {
194 193 float: left;
195 194 width: 29.75%;
196 195 min-height: 150px;
197 196 margin: @sidebarpadding 2% 0 0;
198 197 padding: 0 2% 0 0;
199 198 border-right: @border-thickness solid @grey5;
200 199
201 200 @media (max-width:767px) {
202 201 clear: both;
203 202 width: 100%;
204 203 border: none;
205 204 }
206 205
207 206 ul {
208 207 padding-left: 1.25em;
209 208 }
210 209
211 210 &:last-child {
212 211 margin: @sidebarpadding 0 0;
213 212 border: none;
214 213 }
215 214
216 215 h4 {
217 216 margin: 0 0 @padding;
218 217 font-family: @text-semibold;
219 218 }
220 219 }
221 220 }
222 221 .error-page-logo {
223 222 width: 130px;
224 223 height: 160px;
225 224 }
226 225
227 226 // HEADER
228 227 .header {
229 228
230 229 // TODO: johbo: Fix login pages, so that they work without a min-height
231 230 // for the header and then remove the min-height. I chose a smaller value
232 231 // intentionally here to avoid rendering issues in the main navigation.
233 232 min-height: 49px;
234 233
235 234 position: relative;
236 235 vertical-align: bottom;
237 236 padding: 0 @header-padding;
238 237 background-color: @grey2;
239 238 color: @grey5;
240 239
241 240 .title {
242 241 overflow: visible;
243 242 }
244 243
245 244 &:before,
246 245 &:after {
247 246 content: "";
248 247 clear: both;
249 248 width: 100%;
250 249 }
251 250
252 251 // TODO: johbo: Avoids breaking "Repositories" chooser
253 252 .select2-container .select2-choice .select2-arrow {
254 253 display: none;
255 254 }
256 255 }
257 256
258 257 #header-inner {
259 258 &.title {
260 259 margin: 0;
261 260 }
262 261 &:before,
263 262 &:after {
264 263 content: "";
265 264 clear: both;
266 265 }
267 266 }
268 267
269 268 // Gists
270 269 #files_data {
271 270 clear: both; //for firefox
272 271 }
273 272 #gistid {
274 273 margin-right: @padding;
275 274 }
276 275
277 276 // Global Settings Editor
278 277 .textarea.editor {
279 278 float: left;
280 279 position: relative;
281 280 max-width: @texteditor-width;
282 281
283 282 select {
284 283 position: absolute;
285 284 top:10px;
286 285 right:0;
287 286 }
288 287
289 288 .CodeMirror {
290 289 margin: 0;
291 290 }
292 291
293 292 .help-block {
294 293 margin: 0 0 @padding;
295 294 padding:.5em;
296 295 background-color: @grey6;
297 296 &.pre-formatting {
298 297 white-space: pre;
299 298 }
300 299 }
301 300 }
302 301
303 302 ul.auth_plugins {
304 303 margin: @padding 0 @padding @legend-width;
305 304 padding: 0;
306 305
307 306 li {
308 307 margin-bottom: @padding;
309 308 line-height: 1em;
310 309 list-style-type: none;
311 310
312 311 .auth_buttons .btn {
313 312 margin-right: @padding;
314 313 }
315 314
316 315 &:before { content: none; }
317 316 }
318 317 }
319 318
320 319
321 320 // My Account PR list
322 321
323 322 #show_closed {
324 323 margin: 0 1em 0 0;
325 324 }
326 325
327 326 .pullrequestlist {
328 327 .closed {
329 328 background-color: @grey6;
330 329 }
331 330 .td-status {
332 331 padding-left: .5em;
333 332 }
334 333 .log-container .truncate {
335 334 height: 2.75em;
336 335 white-space: pre-line;
337 336 }
338 337 table.rctable .user {
339 338 padding-left: 0;
340 339 }
341 340 table.rctable {
342 341 td.td-description,
343 342 .rc-user {
344 343 min-width: auto;
345 344 }
346 345 }
347 346 }
348 347
349 348 // Pull Requests
350 349
351 350 .pullrequests_section_head {
352 351 display: block;
353 352 clear: both;
354 353 margin: @padding 0;
355 354 font-family: @text-bold;
356 355 }
357 356
358 357 .pr-origininfo, .pr-targetinfo {
359 358 position: relative;
360 359
361 360 .tag {
362 361 display: inline-block;
363 362 margin: 0 1em .5em 0;
364 363 }
365 364
366 365 .clone-url {
367 366 display: inline-block;
368 367 margin: 0 0 .5em 0;
369 368 padding: 0;
370 369 line-height: 1.2em;
371 370 }
372 371 }
373 372
374 373 .pr-mergeinfo {
375 374 min-width: 95% !important;
376 375 padding: 0 !important;
377 376 border: 0;
378 377 }
379 378 .pr-mergeinfo-copy {
380 379 padding: 0 0;
381 380 }
382 381
383 382 .pr-pullinfo {
384 383 min-width: 95% !important;
385 384 padding: 0 !important;
386 385 border: 0;
387 386 }
388 387 .pr-pullinfo-copy {
389 388 padding: 0 0;
390 389 }
391 390
392 391
393 392 #pr-title-input {
394 393 width: 72%;
395 394 font-size: 1em;
396 395 font-family: @text-bold;
397 396 margin: 0;
398 397 padding: 0 0 0 @padding/4;
399 398 line-height: 1.7em;
400 399 color: @text-color;
401 400 letter-spacing: .02em;
402 401 }
403 402
404 403 #pullrequest_title {
405 404 width: 100%;
406 405 box-sizing: border-box;
407 406 }
408 407
409 408 #pr_open_message {
410 409 border: @border-thickness solid #fff;
411 410 border-radius: @border-radius;
412 411 padding: @padding-large-vertical @padding-large-vertical @padding-large-vertical 0;
413 412 text-align: left;
414 413 overflow: hidden;
415 414 }
416 415
417 416 .pr-submit-button {
418 417 float: right;
419 418 margin: 0 0 0 5px;
420 419 }
421 420
422 421 .pr-spacing-container {
423 422 padding: 20px;
424 423 clear: both
425 424 }
426 425
427 426 #pr-description-input {
428 427 margin-bottom: 0;
429 428 }
430 429
431 430 .pr-description-label {
432 431 vertical-align: top;
433 432 }
434 433
435 434 .perms_section_head {
436 435 min-width: 625px;
437 436
438 437 h2 {
439 438 margin-bottom: 0;
440 439 }
441 440
442 441 .label-checkbox {
443 442 float: left;
444 443 }
445 444
446 445 &.field {
447 446 margin: @space 0 @padding;
448 447 }
449 448
450 449 &:first-child.field {
451 450 margin-top: 0;
452 451
453 452 .label {
454 453 margin-top: 0;
455 454 padding-top: 0;
456 455 }
457 456
458 457 .radios {
459 458 padding-top: 0;
460 459 }
461 460 }
462 461
463 462 .radios {
464 463 position: relative;
465 464 width: 505px;
466 465 }
467 466 }
468 467
469 468 //--- MODULES ------------------//
470 469
471 470
472 471 // Server Announcement
473 472 #server-announcement {
474 473 width: 95%;
475 474 margin: @padding auto;
476 475 padding: @padding;
477 476 border-width: 2px;
478 477 border-style: solid;
479 478 .border-radius(2px);
480 479 font-family: @text-bold;
481 480
482 481 &.info { border-color: @alert4; background-color: @alert4-inner; }
483 482 &.warning { border-color: @alert3; background-color: @alert3-inner; }
484 483 &.error { border-color: @alert2; background-color: @alert2-inner; }
485 484 &.success { border-color: @alert1; background-color: @alert1-inner; }
486 485 &.neutral { border-color: @grey3; background-color: @grey6; }
487 486 }
488 487
489 488 // Fixed Sidebar Column
490 489 .sidebar-col-wrapper {
491 490 padding-left: @sidebar-all-width;
492 491
493 492 .sidebar {
494 493 width: @sidebar-width;
495 494 margin-left: -@sidebar-all-width;
496 495 }
497 496 }
498 497
499 498 .sidebar-col-wrapper.scw-small {
500 499 padding-left: @sidebar-small-all-width;
501 500
502 501 .sidebar {
503 502 width: @sidebar-small-width;
504 503 margin-left: -@sidebar-small-all-width;
505 504 }
506 505 }
507 506
508 507
509 508 // FOOTER
510 509 #footer {
511 510 padding: 0;
512 511 text-align: center;
513 512 vertical-align: middle;
514 513 color: @grey2;
515 514 background-color: @grey6;
516 515
517 516 p {
518 517 margin: 0;
519 518 padding: 1em;
520 519 line-height: 1em;
521 520 }
522 521
523 522 .server-instance { //server instance
524 523 display: none;
525 524 }
526 525
527 526 .title {
528 527 float: none;
529 528 margin: 0 auto;
530 529 }
531 530 }
532 531
533 532 button.close {
534 533 padding: 0;
535 534 cursor: pointer;
536 535 background: transparent;
537 536 border: 0;
538 537 .box-shadow(none);
539 538 -webkit-appearance: none;
540 539 }
541 540
542 541 .close {
543 542 float: right;
544 543 font-size: 21px;
545 544 font-family: @text-bootstrap;
546 545 line-height: 1em;
547 546 font-weight: bold;
548 547 color: @grey2;
549 548
550 549 &:hover,
551 550 &:focus {
552 551 color: @grey1;
553 552 text-decoration: none;
554 553 cursor: pointer;
555 554 }
556 555 }
557 556
558 557 // GRID
559 558 .sorting,
560 559 .sorting_desc,
561 560 .sorting_asc {
562 561 cursor: pointer;
563 562 }
564 563 .sorting_desc:after {
565 564 content: "\00A0\25B2";
566 565 font-size: .75em;
567 566 }
568 567 .sorting_asc:after {
569 568 content: "\00A0\25BC";
570 569 font-size: .68em;
571 570 }
572 571
573 572
574 573 .user_auth_tokens {
575 574
576 575 &.truncate {
577 576 white-space: nowrap;
578 577 overflow: hidden;
579 578 text-overflow: ellipsis;
580 579 }
581 580
582 581 .fields .field .input {
583 582 margin: 0;
584 583 }
585 584
586 585 input#description {
587 586 width: 100px;
588 587 margin: 0;
589 588 }
590 589
591 590 .drop-menu {
592 591 // TODO: johbo: Remove this, should work out of the box when
593 592 // having multiple inputs inline
594 593 margin: 0 0 0 5px;
595 594 }
596 595 }
597 596 #user_list_table {
598 597 .closed {
599 598 background-color: @grey6;
600 599 }
601 600 }
602 601
603 602
604 603 input {
605 604 &.disabled {
606 605 opacity: .5;
607 606 }
608 607 }
609 608
610 609 // remove extra padding in firefox
611 610 input::-moz-focus-inner { border:0; padding:0 }
612 611
613 612 .adjacent input {
614 613 margin-bottom: @padding;
615 614 }
616 615
617 616 .permissions_boxes {
618 617 display: block;
619 618 }
620 619
621 620 //TODO: lisa: this should be in tables
622 621 .show_more_col {
623 622 width: 20px;
624 623 }
625 624
626 625 //FORMS
627 626
628 627 .medium-inline,
629 628 input#description.medium-inline {
630 629 display: inline;
631 630 width: @medium-inline-input-width;
632 631 min-width: 100px;
633 632 }
634 633
635 634 select {
636 635 //reset
637 636 -webkit-appearance: none;
638 637 -moz-appearance: none;
639 638
640 639 display: inline-block;
641 640 height: 28px;
642 641 width: auto;
643 642 margin: 0 @padding @padding 0;
644 643 padding: 0 18px 0 8px;
645 644 line-height:1em;
646 645 font-size: @basefontsize;
647 646 border: @border-thickness solid @rcblue;
648 647 background:white url("../images/dt-arrow-dn.png") no-repeat 100% 50%;
649 648 color: @rcblue;
650 649
651 650 &:after {
652 651 content: "\00A0\25BE";
653 652 }
654 653
655 654 &:focus {
656 655 outline: none;
657 656 }
658 657 }
659 658
660 659 option {
661 660 &:focus {
662 661 outline: none;
663 662 }
664 663 }
665 664
666 665 input,
667 666 textarea {
668 667 padding: @input-padding;
669 668 border: @input-border-thickness solid @border-highlight-color;
670 669 .border-radius (@border-radius);
671 670 font-family: @text-light;
672 671 font-size: @basefontsize;
673 672
674 673 &.input-sm {
675 674 padding: 5px;
676 675 }
677 676
678 677 &#description {
679 678 min-width: @input-description-minwidth;
680 679 min-height: 1em;
681 680 padding: 10px;
682 681 }
683 682 }
684 683
685 684 .field-sm {
686 685 input,
687 686 textarea {
688 687 padding: 5px;
689 688 }
690 689 }
691 690
692 691 textarea {
693 692 display: block;
694 693 clear: both;
695 694 width: 100%;
696 695 min-height: 100px;
697 696 margin-bottom: @padding;
698 697 .box-sizing(border-box);
699 698 overflow: auto;
700 699 }
701 700
702 701 label {
703 702 font-family: @text-light;
704 703 }
705 704
706 705 // GRAVATARS
707 706 // centers gravatar on username to the right
708 707
709 708 .gravatar {
710 709 display: inline;
711 710 min-width: 16px;
712 711 min-height: 16px;
713 712 margin: -5px 0;
714 713 padding: 0;
715 714 line-height: 1em;
716 715 border: 1px solid @grey4;
717 716 box-sizing: content-box;
718 717
719 718 &.gravatar-large {
720 719 margin: -0.5em .25em -0.5em 0;
721 720 }
722 721
723 722 & + .user {
724 723 display: inline;
725 724 margin: 0;
726 725 padding: 0 0 0 .17em;
727 726 line-height: 1em;
728 727 }
729 728 }
730 729
731 730 .user-inline-data {
732 731 display: inline-block;
733 732 float: left;
734 733 padding-left: .5em;
735 734 line-height: 1.3em;
736 735 }
737 736
738 737 .rc-user { // gravatar + user wrapper
739 738 float: left;
740 739 position: relative;
741 740 min-width: 100px;
742 741 max-width: 200px;
743 742 min-height: (@gravatar-size + @border-thickness * 2); // account for border
744 743 display: block;
745 744 padding: 0 0 0 (@gravatar-size + @basefontsize/2 + @border-thickness * 2);
746 745
747 746
748 747 .gravatar {
749 748 display: block;
750 749 position: absolute;
751 750 top: 0;
752 751 left: 0;
753 752 min-width: @gravatar-size;
754 753 min-height: @gravatar-size;
755 754 margin: 0;
756 755 }
757 756
758 757 .user {
759 758 display: block;
760 759 max-width: 175px;
761 760 padding-top: 2px;
762 761 overflow: hidden;
763 762 text-overflow: ellipsis;
764 763 }
765 764 }
766 765
767 766 .gist-gravatar,
768 767 .journal_container {
769 768 .gravatar-large {
770 769 margin: 0 .5em -10px 0;
771 770 }
772 771 }
773 772
774 773
775 774 // ADMIN SETTINGS
776 775
777 776 // Tag Patterns
778 777 .tag_patterns {
779 778 .tag_input {
780 779 margin-bottom: @padding;
781 780 }
782 781 }
783 782
784 783 .locked_input {
785 784 position: relative;
786 785
787 786 input {
788 787 display: inline;
789 788 margin: 3px 5px 0px 0px;
790 789 }
791 790
792 791 br {
793 792 display: none;
794 793 }
795 794
796 795 .error-message {
797 796 float: left;
798 797 width: 100%;
799 798 }
800 799
801 800 .lock_input_button {
802 801 display: inline;
803 802 }
804 803
805 804 .help-block {
806 805 clear: both;
807 806 }
808 807 }
809 808
810 809 // Notifications
811 810
812 811 .notifications_buttons {
813 812 margin: 0 0 @space 0;
814 813 padding: 0;
815 814
816 815 .btn {
817 816 display: inline-block;
818 817 }
819 818 }
820 819
821 820 .notification-list {
822 821
823 822 div {
824 823 display: inline-block;
825 824 vertical-align: middle;
826 825 }
827 826
828 827 .container {
829 828 display: block;
830 829 margin: 0 0 @padding 0;
831 830 }
832 831
833 832 .delete-notifications {
834 833 margin-left: @padding;
835 834 text-align: right;
836 835 cursor: pointer;
837 836 }
838 837
839 838 .read-notifications {
840 839 margin-left: @padding/2;
841 840 text-align: right;
842 841 width: 35px;
843 842 cursor: pointer;
844 843 }
845 844
846 845 .icon-minus-sign {
847 846 color: @alert2;
848 847 }
849 848
850 849 .icon-ok-sign {
851 850 color: @alert1;
852 851 }
853 852 }
854 853
855 854 .user_settings {
856 855 float: left;
857 856 clear: both;
858 857 display: block;
859 858 width: 100%;
860 859
861 860 .gravatar_box {
862 861 margin-bottom: @padding;
863 862
864 863 &:after {
865 864 content: " ";
866 865 clear: both;
867 866 width: 100%;
868 867 }
869 868 }
870 869
871 870 .fields .field {
872 871 clear: both;
873 872 }
874 873 }
875 874
876 875 .advanced_settings {
877 876 margin-bottom: @space;
878 877
879 878 .help-block {
880 879 margin-left: 0;
881 880 }
882 881
883 882 button + .help-block {
884 883 margin-top: @padding;
885 884 }
886 885 }
887 886
888 887 // admin settings radio buttons and labels
889 888 .label-2 {
890 889 float: left;
891 890 width: @label2-width;
892 891
893 892 label {
894 893 color: @grey1;
895 894 }
896 895 }
897 896 .checkboxes {
898 897 float: left;
899 898 width: @checkboxes-width;
900 899 margin-bottom: @padding;
901 900
902 901 .checkbox {
903 902 width: 100%;
904 903
905 904 label {
906 905 margin: 0;
907 906 padding: 0;
908 907 }
909 908 }
910 909
911 910 .checkbox + .checkbox {
912 911 display: inline-block;
913 912 }
914 913
915 914 label {
916 915 margin-right: 1em;
917 916 }
918 917 }
919 918
920 919 // CHANGELOG
921 920 .container_header {
922 921 float: left;
923 922 display: block;
924 923 width: 100%;
925 924 margin: @padding 0 @padding;
926 925
927 926 #filter_changelog {
928 927 float: left;
929 928 margin-right: @padding;
930 929 }
931 930
932 931 .breadcrumbs_light {
933 932 display: inline-block;
934 933 }
935 934 }
936 935
937 936 .info_box {
938 937 float: right;
939 938 }
940 939
941 940
942 941 #graph_nodes {
943 942 padding-top: 43px;
944 943 }
945 944
946 945 #graph_content{
947 946
948 947 // adjust for table headers so that graph renders properly
949 948 // #graph_nodes padding - table cell padding
950 949 padding-top: (@space - (@basefontsize * 2.4));
951 950
952 951 &.graph_full_width {
953 952 width: 100%;
954 953 max-width: 100%;
955 954 }
956 955 }
957 956
958 957 #graph {
959 958 .flag_status {
960 959 margin: 0;
961 960 }
962 961
963 962 .pagination-left {
964 963 float: left;
965 964 clear: both;
966 965 }
967 966
968 967 .log-container {
969 968 max-width: 345px;
970 969
971 970 .message{
972 971 max-width: 340px;
973 972 }
974 973 }
975 974
976 975 .graph-col-wrapper {
977 976 padding-left: 110px;
978 977
979 978 #graph_nodes {
980 979 width: 100px;
981 980 margin-left: -110px;
982 981 float: left;
983 982 clear: left;
984 983 }
985 984 }
986 985
987 986 .load-more-commits {
988 987 text-align: center;
989 988 }
990 989 .load-more-commits:hover {
991 990 background-color: @grey7;
992 991 }
993 992 .load-more-commits {
994 993 a {
995 994 display: block;
996 995 }
997 996 }
998 997 }
999 998
1000 999 #filter_changelog {
1001 1000 float: left;
1002 1001 }
1003 1002
1004 1003
1005 1004 //--- THEME ------------------//
1006 1005
1007 1006 #logo {
1008 1007 float: left;
1009 1008 margin: 9px 0 0 0;
1010 1009
1011 1010 .header {
1012 1011 background-color: transparent;
1013 1012 }
1014 1013
1015 1014 a {
1016 1015 display: inline-block;
1017 1016 }
1018 1017
1019 1018 img {
1020 1019 height:30px;
1021 1020 }
1022 1021 }
1023 1022
1024 1023 .logo-wrapper {
1025 1024 float:left;
1026 1025 }
1027 1026
1028 1027 .branding{
1029 1028 float: left;
1030 1029 padding: 9px 2px;
1031 1030 line-height: 1em;
1032 1031 font-size: @navigation-fontsize;
1033 1032 }
1034 1033
1035 1034 img {
1036 1035 border: none;
1037 1036 outline: none;
1038 1037 }
1039 1038 user-profile-header
1040 1039 label {
1041 1040
1042 1041 input[type="checkbox"] {
1043 1042 margin-right: 1em;
1044 1043 }
1045 1044 input[type="radio"] {
1046 1045 margin-right: 1em;
1047 1046 }
1048 1047 }
1049 1048
1050 1049 .flag_status {
1051 1050 margin: 2px 8px 6px 2px;
1052 1051 &.under_review {
1053 1052 .circle(5px, @alert3);
1054 1053 }
1055 1054 &.approved {
1056 1055 .circle(5px, @alert1);
1057 1056 }
1058 1057 &.rejected,
1059 1058 &.forced_closed{
1060 1059 .circle(5px, @alert2);
1061 1060 }
1062 1061 &.not_reviewed {
1063 1062 .circle(5px, @grey5);
1064 1063 }
1065 1064 }
1066 1065
1067 1066 .flag_status_comment_box {
1068 1067 margin: 5px 6px 0px 2px;
1069 1068 }
1070 1069 .test_pattern_preview {
1071 1070 margin: @space 0;
1072 1071
1073 1072 p {
1074 1073 margin-bottom: 0;
1075 1074 border-bottom: @border-thickness solid @border-default-color;
1076 1075 color: @grey3;
1077 1076 }
1078 1077
1079 1078 .btn {
1080 1079 margin-bottom: @padding;
1081 1080 }
1082 1081 }
1083 1082 #test_pattern_result {
1084 1083 display: none;
1085 1084 &:extend(pre);
1086 1085 padding: .9em;
1087 1086 color: @grey3;
1088 1087 background-color: @grey7;
1089 1088 border-right: @border-thickness solid @border-default-color;
1090 1089 border-bottom: @border-thickness solid @border-default-color;
1091 1090 border-left: @border-thickness solid @border-default-color;
1092 1091 }
1093 1092
1094 1093 #repo_vcs_settings {
1095 1094 #inherit_overlay_vcs_default {
1096 1095 display: none;
1097 1096 }
1098 1097 #inherit_overlay_vcs_custom {
1099 1098 display: custom;
1100 1099 }
1101 1100 &.inherited {
1102 1101 #inherit_overlay_vcs_default {
1103 1102 display: block;
1104 1103 }
1105 1104 #inherit_overlay_vcs_custom {
1106 1105 display: none;
1107 1106 }
1108 1107 }
1109 1108 }
1110 1109
1111 1110 .issue-tracker-link {
1112 1111 color: @rcblue;
1113 1112 }
1114 1113
1115 1114 // Issue Tracker Table Show/Hide
1116 1115 #repo_issue_tracker {
1117 1116 #inherit_overlay {
1118 1117 display: none;
1119 1118 }
1120 1119 #custom_overlay {
1121 1120 display: custom;
1122 1121 }
1123 1122 &.inherited {
1124 1123 #inherit_overlay {
1125 1124 display: block;
1126 1125 }
1127 1126 #custom_overlay {
1128 1127 display: none;
1129 1128 }
1130 1129 }
1131 1130 }
1132 1131 table.issuetracker {
1133 1132 &.readonly {
1134 1133 tr, td {
1135 1134 color: @grey3;
1136 1135 }
1137 1136 }
1138 1137 .edit {
1139 1138 display: none;
1140 1139 }
1141 1140 .editopen {
1142 1141 .edit {
1143 1142 display: inline;
1144 1143 }
1145 1144 .entry {
1146 1145 display: none;
1147 1146 }
1148 1147 }
1149 1148 tr td.td-action {
1150 1149 min-width: 117px;
1151 1150 }
1152 1151 td input {
1153 1152 max-width: none;
1154 1153 min-width: 30px;
1155 1154 width: 80%;
1156 1155 }
1157 1156 .issuetracker_pref input {
1158 1157 width: 40%;
1159 1158 }
1160 1159 input.edit_issuetracker_update {
1161 1160 margin-right: 0;
1162 1161 width: auto;
1163 1162 }
1164 1163 }
1165 1164
1166 1165 table.integrations {
1167 1166 .td-icon {
1168 1167 width: 20px;
1169 1168 .integration-icon {
1170 1169 height: 20px;
1171 1170 width: 20px;
1172 1171 }
1173 1172 }
1174 1173 }
1175 1174
1176 1175 .integrations {
1177 1176 a.integration-box {
1178 1177 color: @text-color;
1179 1178 &:hover {
1180 1179 .panel {
1181 1180 background: #fbfbfb;
1182 1181 }
1183 1182 }
1184 1183 .integration-icon {
1185 1184 width: 30px;
1186 1185 height: 30px;
1187 1186 margin-right: 20px;
1188 1187 float: left;
1189 1188 }
1190 1189
1191 1190 .panel-body {
1192 1191 padding: 10px;
1193 1192 }
1194 1193 .panel {
1195 1194 margin-bottom: 10px;
1196 1195 }
1197 1196 h2 {
1198 1197 display: inline-block;
1199 1198 margin: 0;
1200 1199 min-width: 140px;
1201 1200 }
1202 1201 }
1203 1202 a.integration-box.dummy-integration {
1204 1203 color: @grey4
1205 1204 }
1206 1205 }
1207 1206
1208 1207 //Permissions Settings
1209 1208 #add_perm {
1210 1209 margin: 0 0 @padding;
1211 1210 cursor: pointer;
1212 1211 }
1213 1212
1214 1213 .perm_ac {
1215 1214 input {
1216 1215 width: 95%;
1217 1216 }
1218 1217 }
1219 1218
1220 1219 .autocomplete-suggestions {
1221 1220 width: auto !important; // overrides autocomplete.js
1222 1221 margin: 0;
1223 1222 border: @border-thickness solid @rcblue;
1224 1223 border-radius: @border-radius;
1225 1224 color: @rcblue;
1226 1225 background-color: white;
1227 1226 }
1228 1227 .autocomplete-selected {
1229 1228 background: #F0F0F0;
1230 1229 }
1231 1230 .ac-container-wrap {
1232 1231 margin: 0;
1233 1232 padding: 8px;
1234 1233 border-bottom: @border-thickness solid @rclightblue;
1235 1234 list-style-type: none;
1236 1235 cursor: pointer;
1237 1236
1238 1237 &:hover {
1239 1238 background-color: @rclightblue;
1240 1239 }
1241 1240
1242 1241 img {
1243 1242 height: @gravatar-size;
1244 1243 width: @gravatar-size;
1245 1244 margin-right: 1em;
1246 1245 }
1247 1246
1248 1247 strong {
1249 1248 font-weight: normal;
1250 1249 }
1251 1250 }
1252 1251
1253 1252 // Settings Dropdown
1254 1253 .user-menu .container {
1255 1254 padding: 0 4px;
1256 1255 margin: 0;
1257 1256 }
1258 1257
1259 1258 .user-menu .gravatar {
1260 1259 cursor: pointer;
1261 1260 }
1262 1261
1263 1262 .codeblock {
1264 1263 margin-bottom: @padding;
1265 1264 clear: both;
1266 1265
1267 1266 .stats{
1268 1267 overflow: hidden;
1269 1268 }
1270 1269
1271 1270 .message{
1272 1271 textarea{
1273 1272 margin: 0;
1274 1273 }
1275 1274 }
1276 1275
1277 1276 .code-header {
1278 1277 .stats {
1279 1278 line-height: 2em;
1280 1279
1281 1280 .revision_id {
1282 1281 margin-left: 0;
1283 1282 }
1284 1283 .buttons {
1285 1284 padding-right: 0;
1286 1285 }
1287 1286 }
1288 1287
1289 1288 .item{
1290 1289 margin-right: 0.5em;
1291 1290 }
1292 1291 }
1293 1292
1294 1293 #editor_container{
1295 1294 position: relative;
1296 1295 margin: @padding;
1297 1296 }
1298 1297 }
1299 1298
1300 1299 #file_history_container {
1301 1300 display: none;
1302 1301 }
1303 1302
1304 1303 .file-history-inner {
1305 1304 margin-bottom: 10px;
1306 1305 }
1307 1306
1308 1307 // Pull Requests
1309 1308 .summary-details {
1310 1309 width: 72%;
1311 1310 }
1312 1311 .pr-summary {
1313 1312 border-bottom: @border-thickness solid @grey5;
1314 1313 margin-bottom: @space;
1315 1314 }
1316 1315 .reviewers-title {
1317 1316 width: 25%;
1318 1317 min-width: 200px;
1319 1318 }
1320 1319 .reviewers {
1321 1320 width: 25%;
1322 1321 min-width: 200px;
1323 1322 }
1324 1323 .reviewers ul li {
1325 1324 position: relative;
1326 1325 width: 100%;
1327 1326 padding-bottom: 8px;
1328 1327 }
1329 1328
1330 1329 .reviewer_entry {
1331 1330 min-height: 55px;
1332 1331 }
1333 1332
1334 1333 .reviewers_member {
1335 1334 width: 100%;
1336 1335 overflow: auto;
1337 1336 }
1338 1337 .reviewer_reason {
1339 1338 padding-left: 20px;
1340 1339 line-height: 1.5em;
1341 1340 }
1342 1341 .reviewer_status {
1343 1342 display: inline-block;
1344 1343 vertical-align: top;
1345 1344 width: 25px;
1346 1345 min-width: 25px;
1347 1346 height: 1.2em;
1348 1347 margin-top: 3px;
1349 1348 line-height: 1em;
1350 1349 }
1351 1350
1352 1351 .reviewer_name {
1353 1352 display: inline-block;
1354 1353 max-width: 83%;
1355 1354 padding-right: 20px;
1356 1355 vertical-align: middle;
1357 1356 line-height: 1;
1358 1357
1359 1358 .rc-user {
1360 1359 min-width: 0;
1361 1360 margin: -2px 1em 0 0;
1362 1361 }
1363 1362
1364 1363 .reviewer {
1365 1364 float: left;
1366 1365 }
1367 1366 }
1368 1367
1369 1368 .reviewer_member_mandatory {
1370 1369 position: absolute;
1371 1370 left: 15px;
1372 1371 top: 8px;
1373 1372 width: 16px;
1374 1373 font-size: 11px;
1375 1374 margin: 0;
1376 1375 padding: 0;
1377 1376 color: black;
1378 1377 }
1379 1378
1380 1379 .reviewer_member_mandatory_remove,
1381 1380 .reviewer_member_remove {
1382 1381 position: absolute;
1383 1382 right: 0;
1384 1383 top: 0;
1385 1384 width: 16px;
1386 1385 margin-bottom: 10px;
1387 1386 padding: 0;
1388 1387 color: black;
1389 1388 }
1390 1389
1391 1390 .reviewer_member_mandatory_remove {
1392 1391 color: @grey4;
1393 1392 }
1394 1393
1395 1394 .reviewer_member_status {
1396 1395 margin-top: 5px;
1397 1396 }
1398 1397 .pr-summary #summary{
1399 1398 width: 100%;
1400 1399 }
1401 1400 .pr-summary .action_button:hover {
1402 1401 border: 0;
1403 1402 cursor: pointer;
1404 1403 }
1405 1404 .pr-details-title {
1406 1405 padding-bottom: 8px;
1407 1406 border-bottom: @border-thickness solid @grey5;
1408 1407
1409 1408 .action_button.disabled {
1410 1409 color: @grey4;
1411 1410 cursor: inherit;
1412 1411 }
1413 1412 .action_button {
1414 1413 color: @rcblue;
1415 1414 }
1416 1415 }
1417 1416 .pr-details-content {
1418 1417 margin-top: @textmargin;
1419 1418 margin-bottom: @textmargin;
1420 1419 }
1421 1420
1422 1421 .pr-reviewer-rules {
1423 1422 padding: 10px 0px 20px 0px;
1424 1423 }
1425 1424
1426 1425 .group_members {
1427 1426 margin-top: 0;
1428 1427 padding: 0;
1429 1428 list-style: outside none none;
1430 1429
1431 1430 img {
1432 1431 height: @gravatar-size;
1433 1432 width: @gravatar-size;
1434 1433 margin-right: .5em;
1435 1434 margin-left: 3px;
1436 1435 }
1437 1436
1438 1437 .to-delete {
1439 1438 .user {
1440 1439 text-decoration: line-through;
1441 1440 }
1442 1441 }
1443 1442 }
1444 1443
1445 1444 .compare_view_commits_title {
1446 1445 .disabled {
1447 1446 cursor: inherit;
1448 1447 &:hover{
1449 1448 background-color: inherit;
1450 1449 color: inherit;
1451 1450 }
1452 1451 }
1453 1452 }
1454 1453
1455 1454 .subtitle-compare {
1456 1455 margin: -15px 0px 0px 0px;
1457 1456 }
1458 1457
1459 1458 .comments-summary-td {
1460 1459 border-top: 1px dashed @grey5;
1461 1460 }
1462 1461
1463 1462 // new entry in group_members
1464 1463 .td-author-new-entry {
1465 1464 background-color: rgba(red(@alert1), green(@alert1), blue(@alert1), 0.3);
1466 1465 }
1467 1466
1468 1467 .usergroup_member_remove {
1469 1468 width: 16px;
1470 1469 margin-bottom: 10px;
1471 1470 padding: 0;
1472 1471 color: black !important;
1473 1472 cursor: pointer;
1474 1473 }
1475 1474
1476 1475 .reviewer_ac .ac-input {
1477 1476 width: 92%;
1478 1477 margin-bottom: 1em;
1479 1478 }
1480 1479
1481 1480 .compare_view_commits tr{
1482 1481 height: 20px;
1483 1482 }
1484 1483 .compare_view_commits td {
1485 1484 vertical-align: top;
1486 1485 padding-top: 10px;
1487 1486 }
1488 1487 .compare_view_commits .author {
1489 1488 margin-left: 5px;
1490 1489 }
1491 1490
1492 1491 .compare_view_commits {
1493 1492 .color-a {
1494 1493 color: @alert1;
1495 1494 }
1496 1495
1497 1496 .color-c {
1498 1497 color: @color3;
1499 1498 }
1500 1499
1501 1500 .color-r {
1502 1501 color: @color5;
1503 1502 }
1504 1503
1505 1504 .color-a-bg {
1506 1505 background-color: @alert1;
1507 1506 }
1508 1507
1509 1508 .color-c-bg {
1510 1509 background-color: @alert3;
1511 1510 }
1512 1511
1513 1512 .color-r-bg {
1514 1513 background-color: @alert2;
1515 1514 }
1516 1515
1517 1516 .color-a-border {
1518 1517 border: 1px solid @alert1;
1519 1518 }
1520 1519
1521 1520 .color-c-border {
1522 1521 border: 1px solid @alert3;
1523 1522 }
1524 1523
1525 1524 .color-r-border {
1526 1525 border: 1px solid @alert2;
1527 1526 }
1528 1527
1529 1528 .commit-change-indicator {
1530 1529 width: 15px;
1531 1530 height: 15px;
1532 1531 position: relative;
1533 1532 left: 15px;
1534 1533 }
1535 1534
1536 1535 .commit-change-content {
1537 1536 text-align: center;
1538 1537 vertical-align: middle;
1539 1538 line-height: 15px;
1540 1539 }
1541 1540 }
1542 1541
1543 1542 .compare_view_filepath {
1544 1543 color: @grey1;
1545 1544 }
1546 1545
1547 1546 .show_more {
1548 1547 display: inline-block;
1549 position: relative;
1548 width: 0;
1549 height: 0;
1550 1550 vertical-align: middle;
1551 width: 4px;
1552 height: @basefontsize;
1553
1554 &:after {
1555 content: "\00A0\25BE";
1556 display: inline-block;
1557 width:10px;
1558 line-height: 5px;
1559 font-size: 12px;
1560 cursor: pointer;
1561 }
1551 content: "";
1552 border: 4px solid;
1553 border-right-color: transparent;
1554 border-bottom-color: transparent;
1555 border-left-color: transparent;
1556 font-size: 0;
1562 1557 }
1563 1558
1564 1559 .journal_more .show_more {
1565 1560 display: inline;
1566 1561
1567 1562 &:after {
1568 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 1567 .compare_view_commits .collapse_commit:after {
1580 1568 cursor: pointer;
1581 1569 content: "\00A0\25B4";
1582 1570 margin-left: -3px;
1583 1571 font-size: 17px;
1584 1572 color: @grey4;
1585 1573 }
1586 1574
1587 1575 .diff_links {
1588 1576 margin-left: 8px;
1589 1577 }
1590 1578
1591 1579 div.ancestor {
1592 1580 margin: -30px 0px;
1593 1581 }
1594 1582
1595 1583 .cs_icon_td input[type="checkbox"] {
1596 1584 display: none;
1597 1585 }
1598 1586
1599 1587 .cs_icon_td .expand_file_icon:after {
1600 1588 cursor: pointer;
1601 1589 content: "\00A0\25B6";
1602 1590 font-size: 12px;
1603 1591 color: @grey4;
1604 1592 }
1605 1593
1606 1594 .cs_icon_td .collapse_file_icon:after {
1607 1595 cursor: pointer;
1608 1596 content: "\00A0\25BC";
1609 1597 font-size: 12px;
1610 1598 color: @grey4;
1611 1599 }
1612 1600
1613 1601 /*new binary
1614 1602 NEW_FILENODE = 1
1615 1603 DEL_FILENODE = 2
1616 1604 MOD_FILENODE = 3
1617 1605 RENAMED_FILENODE = 4
1618 1606 COPIED_FILENODE = 5
1619 1607 CHMOD_FILENODE = 6
1620 1608 BIN_FILENODE = 7
1621 1609 */
1622 1610 .cs_files_expand {
1623 1611 font-size: @basefontsize + 5px;
1624 1612 line-height: 1.8em;
1625 1613 float: right;
1626 1614 }
1627 1615
1628 1616 .cs_files_expand span{
1629 1617 color: @rcblue;
1630 1618 cursor: pointer;
1631 1619 }
1632 1620 .cs_files {
1633 1621 clear: both;
1634 1622 padding-bottom: @padding;
1635 1623
1636 1624 .cur_cs {
1637 1625 margin: 10px 2px;
1638 1626 font-weight: bold;
1639 1627 }
1640 1628
1641 1629 .node {
1642 1630 float: left;
1643 1631 }
1644 1632
1645 1633 .changes {
1646 1634 float: right;
1647 1635 color: white;
1648 1636 font-size: @basefontsize - 4px;
1649 1637 margin-top: 4px;
1650 1638 opacity: 0.6;
1651 1639 filter: Alpha(opacity=60); /* IE8 and earlier */
1652 1640
1653 1641 .added {
1654 1642 background-color: @alert1;
1655 1643 float: left;
1656 1644 text-align: center;
1657 1645 }
1658 1646
1659 1647 .deleted {
1660 1648 background-color: @alert2;
1661 1649 float: left;
1662 1650 text-align: center;
1663 1651 }
1664 1652
1665 1653 .bin {
1666 1654 background-color: @alert1;
1667 1655 text-align: center;
1668 1656 }
1669 1657
1670 1658 /*new binary*/
1671 1659 .bin.bin1 {
1672 1660 background-color: @alert1;
1673 1661 text-align: center;
1674 1662 }
1675 1663
1676 1664 /*deleted binary*/
1677 1665 .bin.bin2 {
1678 1666 background-color: @alert2;
1679 1667 text-align: center;
1680 1668 }
1681 1669
1682 1670 /*mod binary*/
1683 1671 .bin.bin3 {
1684 1672 background-color: @grey2;
1685 1673 text-align: center;
1686 1674 }
1687 1675
1688 1676 /*rename file*/
1689 1677 .bin.bin4 {
1690 1678 background-color: @alert4;
1691 1679 text-align: center;
1692 1680 }
1693 1681
1694 1682 /*copied file*/
1695 1683 .bin.bin5 {
1696 1684 background-color: @alert4;
1697 1685 text-align: center;
1698 1686 }
1699 1687
1700 1688 /*chmod file*/
1701 1689 .bin.bin6 {
1702 1690 background-color: @grey2;
1703 1691 text-align: center;
1704 1692 }
1705 1693 }
1706 1694 }
1707 1695
1708 1696 .cs_files .cs_added, .cs_files .cs_A,
1709 1697 .cs_files .cs_added, .cs_files .cs_M,
1710 1698 .cs_files .cs_added, .cs_files .cs_D {
1711 1699 height: 16px;
1712 1700 padding-right: 10px;
1713 1701 margin-top: 7px;
1714 1702 text-align: left;
1715 1703 }
1716 1704
1717 1705 .cs_icon_td {
1718 1706 min-width: 16px;
1719 1707 width: 16px;
1720 1708 }
1721 1709
1722 1710 .pull-request-merge {
1723 1711 border: 1px solid @grey5;
1724 1712 padding: 10px 0px 20px;
1725 1713 margin-top: 10px;
1726 1714 margin-bottom: 20px;
1727 1715 }
1728 1716
1729 1717 .pull-request-merge ul {
1730 1718 padding: 0px 0px;
1731 1719 }
1732 1720
1733 1721 .pull-request-merge li:before{
1734 1722 content:none;
1735 1723 }
1736 1724
1737 1725 .pull-request-merge .pull-request-wrap {
1738 1726 height: auto;
1739 1727 padding: 0px 0px;
1740 1728 text-align: right;
1741 1729 }
1742 1730
1743 1731 .pull-request-merge span {
1744 1732 margin-right: 5px;
1745 1733 }
1746 1734
1747 1735 .pull-request-merge-actions {
1748 1736 min-height: 30px;
1749 1737 padding: 0px 0px;
1750 1738 }
1751 1739
1752 1740 .pull-request-merge-info {
1753 1741 padding: 0px 5px 5px 0px;
1754 1742 }
1755 1743
1756 1744 .merge-status {
1757 1745 margin-right: 5px;
1758 1746 }
1759 1747
1760 1748 .merge-message {
1761 1749 font-size: 1.2em
1762 1750 }
1763 1751
1764 1752 .merge-message.success i,
1765 1753 .merge-icon.success i {
1766 1754 color:@alert1;
1767 1755 }
1768 1756
1769 1757 .merge-message.warning i,
1770 1758 .merge-icon.warning i {
1771 1759 color: @alert3;
1772 1760 }
1773 1761
1774 1762 .merge-message.error i,
1775 1763 .merge-icon.error i {
1776 1764 color:@alert2;
1777 1765 }
1778 1766
1779 1767 .pr-versions {
1780 1768 font-size: 1.1em;
1781 1769
1782 1770 table {
1783 1771 padding: 0px 5px;
1784 1772 }
1785 1773
1786 1774 td {
1787 1775 line-height: 15px;
1788 1776 }
1789 1777
1790 1778 .flag_status {
1791 1779 margin: 0;
1792 1780 }
1793 1781
1794 1782 .compare-radio-button {
1795 1783 position: relative;
1796 1784 top: -3px;
1797 1785 }
1798 1786 }
1799 1787
1800 1788
1801 1789 #close_pull_request {
1802 1790 margin-right: 0px;
1803 1791 }
1804 1792
1805 1793 .empty_data {
1806 1794 color: @grey4;
1807 1795 }
1808 1796
1809 1797 #changeset_compare_view_content {
1810 1798 margin-bottom: @space;
1811 1799 clear: both;
1812 1800 width: 100%;
1813 1801 box-sizing: border-box;
1814 1802 .border-radius(@border-radius);
1815 1803
1816 1804 .help-block {
1817 1805 margin: @padding 0;
1818 1806 color: @text-color;
1819 1807 &.pre-formatting {
1820 1808 white-space: pre;
1821 1809 }
1822 1810 }
1823 1811
1824 1812 .empty_data {
1825 1813 margin: @padding 0;
1826 1814 }
1827 1815
1828 1816 .alert {
1829 1817 margin-bottom: @space;
1830 1818 }
1831 1819 }
1832 1820
1833 1821 .table_disp {
1834 1822 .status {
1835 1823 width: auto;
1836 1824
1837 1825 .flag_status {
1838 1826 float: left;
1839 1827 }
1840 1828 }
1841 1829 }
1842 1830
1843 1831
1844 1832 .creation_in_progress {
1845 1833 color: @grey4
1846 1834 }
1847 1835
1848 1836 .status_box_menu {
1849 1837 margin: 0;
1850 1838 }
1851 1839
1852 1840 .notification-table{
1853 1841 margin-bottom: @space;
1854 1842 display: table;
1855 1843 width: 100%;
1856 1844
1857 1845 .container{
1858 1846 display: table-row;
1859 1847
1860 1848 .notification-header{
1861 1849 border-bottom: @border-thickness solid @border-default-color;
1862 1850 }
1863 1851
1864 1852 .notification-subject{
1865 1853 display: table-cell;
1866 1854 }
1867 1855 }
1868 1856 }
1869 1857
1870 1858 // Notifications
1871 1859 .notification-header{
1872 1860 display: table;
1873 1861 width: 100%;
1874 1862 padding: floor(@basefontsize/2) 0;
1875 1863 line-height: 1em;
1876 1864
1877 1865 .desc, .delete-notifications, .read-notifications{
1878 1866 display: table-cell;
1879 1867 text-align: left;
1880 1868 }
1881 1869
1882 1870 .desc{
1883 1871 width: 1163px;
1884 1872 }
1885 1873
1886 1874 .delete-notifications, .read-notifications{
1887 1875 width: 35px;
1888 1876 min-width: 35px; //fixes when only one button is displayed
1889 1877 }
1890 1878 }
1891 1879
1892 1880 .notification-body {
1893 1881 .markdown-block,
1894 1882 .rst-block {
1895 1883 padding: @padding 0;
1896 1884 }
1897 1885
1898 1886 .notification-subject {
1899 1887 padding: @textmargin 0;
1900 1888 border-bottom: @border-thickness solid @border-default-color;
1901 1889 }
1902 1890 }
1903 1891
1904 1892
1905 1893 .notifications_buttons{
1906 1894 float: right;
1907 1895 }
1908 1896
1909 1897 #notification-status{
1910 1898 display: inline;
1911 1899 }
1912 1900
1913 1901 // Repositories
1914 1902
1915 1903 #summary.fields{
1916 1904 display: table;
1917 1905
1918 1906 .field{
1919 1907 display: table-row;
1920 1908
1921 1909 .label-summary{
1922 1910 display: table-cell;
1923 1911 min-width: @label-summary-minwidth;
1924 1912 padding-top: @padding/2;
1925 1913 padding-bottom: @padding/2;
1926 1914 padding-right: @padding/2;
1927 1915 }
1928 1916
1929 1917 .input{
1930 1918 display: table-cell;
1931 1919 padding: @padding/2;
1932 1920
1933 1921 input{
1934 1922 min-width: 29em;
1935 1923 padding: @padding/4;
1936 1924 }
1937 1925 }
1938 1926 .statistics, .downloads{
1939 1927 .disabled{
1940 1928 color: @grey4;
1941 1929 }
1942 1930 }
1943 1931 }
1944 1932 }
1945 1933
1946 1934 #summary{
1947 1935 width: 70%;
1948 1936 }
1949 1937
1950 1938
1951 1939 // Journal
1952 1940 .journal.title {
1953 1941 h5 {
1954 1942 float: left;
1955 1943 margin: 0;
1956 1944 width: 70%;
1957 1945 }
1958 1946
1959 1947 ul {
1960 1948 float: right;
1961 1949 display: inline-block;
1962 1950 margin: 0;
1963 1951 width: 30%;
1964 1952 text-align: right;
1965 1953
1966 1954 li {
1967 1955 display: inline;
1968 1956 font-size: @journal-fontsize;
1969 1957 line-height: 1em;
1970 1958
1971 1959 &:before { content: none; }
1972 1960 }
1973 1961 }
1974 1962 }
1975 1963
1976 1964 .filterexample {
1977 1965 position: absolute;
1978 1966 top: 95px;
1979 1967 left: @contentpadding;
1980 1968 color: @rcblue;
1981 1969 font-size: 11px;
1982 1970 font-family: @text-regular;
1983 1971 cursor: help;
1984 1972
1985 1973 &:hover {
1986 1974 color: @rcdarkblue;
1987 1975 }
1988 1976
1989 1977 @media (max-width:768px) {
1990 1978 position: relative;
1991 1979 top: auto;
1992 1980 left: auto;
1993 1981 display: block;
1994 1982 }
1995 1983 }
1996 1984
1997 1985
1998 1986 #journal{
1999 1987 margin-bottom: @space;
2000 1988
2001 1989 .journal_day{
2002 1990 margin-bottom: @textmargin/2;
2003 1991 padding-bottom: @textmargin/2;
2004 1992 font-size: @journal-fontsize;
2005 1993 border-bottom: @border-thickness solid @border-default-color;
2006 1994 }
2007 1995
2008 1996 .journal_container{
2009 1997 margin-bottom: @space;
2010 1998
2011 1999 .journal_user{
2012 2000 display: inline-block;
2013 2001 }
2014 2002 .journal_action_container{
2015 2003 display: block;
2016 2004 margin-top: @textmargin;
2017 2005
2018 2006 div{
2019 2007 display: inline;
2020 2008 }
2021 2009
2022 2010 div.journal_action_params{
2023 2011 display: block;
2024 2012 }
2025 2013
2026 2014 div.journal_repo:after{
2027 2015 content: "\A";
2028 2016 white-space: pre;
2029 2017 }
2030 2018
2031 2019 div.date{
2032 2020 display: block;
2033 2021 margin-bottom: @textmargin;
2034 2022 }
2035 2023 }
2036 2024 }
2037 2025 }
2038 2026
2039 2027 // Files
2040 2028 .edit-file-title {
2041 2029 border-bottom: @border-thickness solid @border-default-color;
2042 2030
2043 2031 .breadcrumbs {
2044 2032 margin-bottom: 0;
2045 2033 }
2046 2034 }
2047 2035
2048 2036 .edit-file-fieldset {
2049 2037 margin-top: @sidebarpadding;
2050 2038
2051 2039 .fieldset {
2052 2040 .left-label {
2053 2041 width: 13%;
2054 2042 }
2055 2043 .right-content {
2056 2044 width: 87%;
2057 2045 max-width: 100%;
2058 2046 }
2059 2047 .filename-label {
2060 2048 margin-top: 13px;
2061 2049 }
2062 2050 .commit-message-label {
2063 2051 margin-top: 4px;
2064 2052 }
2065 2053 .file-upload-input {
2066 2054 input {
2067 2055 display: none;
2068 2056 }
2069 2057 margin-top: 10px;
2070 2058 }
2071 2059 .file-upload-label {
2072 2060 margin-top: 10px;
2073 2061 }
2074 2062 p {
2075 2063 margin-top: 5px;
2076 2064 }
2077 2065
2078 2066 }
2079 2067 .custom-path-link {
2080 2068 margin-left: 5px;
2081 2069 }
2082 2070 #commit {
2083 2071 resize: vertical;
2084 2072 }
2085 2073 }
2086 2074
2087 2075 .delete-file-preview {
2088 2076 max-height: 250px;
2089 2077 }
2090 2078
2091 2079 .new-file,
2092 2080 #filter_activate,
2093 2081 #filter_deactivate {
2094 2082 float: left;
2095 2083 margin: 0 0 0 15px;
2096 2084 }
2097 2085
2098 2086 h3.files_location{
2099 2087 line-height: 2.4em;
2100 2088 }
2101 2089
2102 2090 .browser-nav {
2103 2091 display: table;
2104 2092 margin-bottom: @space;
2105 2093
2106 2094
2107 2095 .info_box {
2108 2096 display: inline-table;
2109 2097 height: 2.5em;
2110 2098
2111 2099 .browser-cur-rev, .info_box_elem {
2112 2100 display: table-cell;
2113 2101 vertical-align: middle;
2114 2102 }
2115 2103
2116 2104 .info_box_elem {
2117 2105 border-top: @border-thickness solid @rcblue;
2118 2106 border-bottom: @border-thickness solid @rcblue;
2119 2107
2120 2108 #at_rev, a {
2121 2109 padding: 0.6em 0.9em;
2122 2110 margin: 0;
2123 2111 .box-shadow(none);
2124 2112 border: 0;
2125 2113 height: 12px;
2126 2114 }
2127 2115
2128 2116 input#at_rev {
2129 2117 max-width: 50px;
2130 2118 text-align: right;
2131 2119 }
2132 2120
2133 2121 &.previous {
2134 2122 border: @border-thickness solid @rcblue;
2135 2123 .disabled {
2136 2124 color: @grey4;
2137 2125 cursor: not-allowed;
2138 2126 }
2139 2127 }
2140 2128
2141 2129 &.next {
2142 2130 border: @border-thickness solid @rcblue;
2143 2131 .disabled {
2144 2132 color: @grey4;
2145 2133 cursor: not-allowed;
2146 2134 }
2147 2135 }
2148 2136 }
2149 2137
2150 2138 .browser-cur-rev {
2151 2139
2152 2140 span{
2153 2141 margin: 0;
2154 2142 color: @rcblue;
2155 2143 height: 12px;
2156 2144 display: inline-block;
2157 2145 padding: 0.7em 1em ;
2158 2146 border: @border-thickness solid @rcblue;
2159 2147 margin-right: @padding;
2160 2148 }
2161 2149 }
2162 2150 }
2163 2151
2164 2152 .search_activate {
2165 2153 display: table-cell;
2166 2154 vertical-align: middle;
2167 2155
2168 2156 input, label{
2169 2157 margin: 0;
2170 2158 padding: 0;
2171 2159 }
2172 2160
2173 2161 input{
2174 2162 margin-left: @textmargin;
2175 2163 }
2176 2164
2177 2165 }
2178 2166 }
2179 2167
2180 2168 .browser-cur-rev{
2181 2169 margin-bottom: @textmargin;
2182 2170 }
2183 2171
2184 2172 #node_filter_box_loading{
2185 2173 .info_text;
2186 2174 }
2187 2175
2188 2176 .browser-search {
2189 2177 margin: -25px 0px 5px 0px;
2190 2178 }
2191 2179
2192 2180 .node-filter {
2193 2181 font-size: @repo-title-fontsize;
2194 2182 padding: 4px 0px 0px 0px;
2195 2183
2196 2184 .node-filter-path {
2197 2185 float: left;
2198 2186 color: @grey4;
2199 2187 }
2200 2188 .node-filter-input {
2201 2189 float: left;
2202 2190 margin: -2px 0px 0px 2px;
2203 2191 input {
2204 2192 padding: 2px;
2205 2193 border: none;
2206 2194 font-size: @repo-title-fontsize;
2207 2195 }
2208 2196 }
2209 2197 }
2210 2198
2211 2199
2212 2200 .browser-result{
2213 2201 td a{
2214 2202 margin-left: 0.5em;
2215 2203 display: inline-block;
2216 2204
2217 2205 em{
2218 2206 font-family: @text-bold;
2219 2207 }
2220 2208 }
2221 2209 }
2222 2210
2223 2211 .browser-highlight{
2224 2212 background-color: @grey5-alpha;
2225 2213 }
2226 2214
2227 2215
2228 2216 // Search
2229 2217
2230 2218 .search-form{
2231 2219 #q {
2232 2220 width: @search-form-width;
2233 2221 }
2234 2222 .fields{
2235 2223 margin: 0 0 @space;
2236 2224 }
2237 2225
2238 2226 label{
2239 2227 display: inline-block;
2240 2228 margin-right: @textmargin;
2241 2229 padding-top: 0.25em;
2242 2230 }
2243 2231
2244 2232
2245 2233 .results{
2246 2234 clear: both;
2247 2235 margin: 0 0 @padding;
2248 2236 }
2249 2237 }
2250 2238
2251 2239 div.search-feedback-items {
2252 2240 display: inline-block;
2253 padding:0px 0px 0px 96px;
2254 2241 }
2255 2242
2256 2243 div.search-code-body {
2257 2244 background-color: #ffffff; padding: 5px 0 5px 10px;
2258 2245 pre {
2259 2246 .match { background-color: #faffa6;}
2260 2247 .break { display: block; width: 100%; background-color: #DDE7EF; color: #747474; }
2261 2248 }
2262 2249 }
2263 2250
2264 2251 .expand_commit.search {
2265 2252 .show_more.open {
2266 2253 height: auto;
2267 2254 max-height: none;
2268 2255 }
2269 2256 }
2270 2257
2271 2258 .search-results {
2272 2259
2273 2260 h2 {
2274 2261 margin-bottom: 0;
2275 2262 }
2276 2263 .codeblock {
2277 2264 border: none;
2278 2265 background: transparent;
2279 2266 }
2280 2267
2281 2268 .codeblock-header {
2282 2269 border: none;
2283 2270 background: transparent;
2284 2271 }
2285 2272
2286 2273 .code-body {
2287 2274 border: @border-thickness solid @border-default-color;
2288 2275 .border-radius(@border-radius);
2289 2276 }
2290 2277
2291 2278 .td-commit {
2292 2279 &:extend(pre);
2293 2280 border-bottom: @border-thickness solid @border-default-color;
2294 2281 }
2295 2282
2296 2283 .message {
2297 2284 height: auto;
2298 2285 max-width: 350px;
2299 2286 white-space: normal;
2300 2287 text-overflow: initial;
2301 2288 overflow: visible;
2302 2289
2303 2290 .match { background-color: #faffa6;}
2304 2291 .break { background-color: #DDE7EF; width: 100%; color: #747474; display: block; }
2305 2292 }
2306 2293
2307 2294 }
2308 2295
2309 2296 table.rctable td.td-search-results div {
2310 2297 max-width: 100%;
2311 2298 }
2312 2299
2313 2300 #tip-box, .tip-box{
2314 2301 padding: @menupadding/2;
2315 2302 display: block;
2316 2303 border: @border-thickness solid @border-highlight-color;
2317 2304 .border-radius(@border-radius);
2318 2305 background-color: white;
2319 2306 z-index: 99;
2320 2307 white-space: pre-wrap;
2321 2308 }
2322 2309
2323 2310 #linktt {
2324 2311 width: 79px;
2325 2312 }
2326 2313
2327 2314 #help_kb .modal-content{
2328 2315 max-width: 750px;
2329 2316 margin: 10% auto;
2330 2317
2331 2318 table{
2332 2319 td,th{
2333 2320 border-bottom: none;
2334 2321 line-height: 2.5em;
2335 2322 }
2336 2323 th{
2337 2324 padding-bottom: @textmargin/2;
2338 2325 }
2339 2326 td.keys{
2340 2327 text-align: center;
2341 2328 }
2342 2329 }
2343 2330
2344 2331 .block-left{
2345 2332 width: 45%;
2346 2333 margin-right: 5%;
2347 2334 }
2348 2335 .modal-footer{
2349 2336 clear: both;
2350 2337 }
2351 2338 .key.tag{
2352 2339 padding: 0.5em;
2353 2340 background-color: @rcblue;
2354 2341 color: white;
2355 2342 border-color: @rcblue;
2356 2343 .box-shadow(none);
2357 2344 }
2358 2345 }
2359 2346
2360 2347
2361 2348
2362 2349 //--- IMPORTS FOR REFACTORED STYLES ------------------//
2363 2350
2364 2351 @import 'statistics-graph';
2365 2352 @import 'tables';
2366 2353 @import 'forms';
2367 2354 @import 'diff';
2368 2355 @import 'summary';
2369 2356 @import 'navigation';
2370 2357
2371 2358 //--- SHOW/HIDE SECTIONS --//
2372 2359
2373 2360 .btn-collapse {
2374 2361 float: right;
2375 2362 text-align: right;
2376 2363 font-family: @text-light;
2377 2364 font-size: @basefontsize;
2378 2365 cursor: pointer;
2379 2366 border: none;
2380 2367 color: @rcblue;
2381 2368 }
2382 2369
2383 2370 table.rctable,
2384 2371 table.dataTable {
2385 2372 .btn-collapse {
2386 2373 float: right;
2387 2374 text-align: right;
2388 2375 }
2389 2376 }
2390 2377
2391 2378
2392 2379 // TODO: johbo: Fix for IE10, this avoids that we see a border
2393 2380 // and padding around checkboxes and radio boxes. Move to the right place,
2394 2381 // or better: Remove this once we did the form refactoring.
2395 2382 input[type=checkbox],
2396 2383 input[type=radio] {
2397 2384 padding: 0;
2398 2385 border: none;
2399 2386 }
2400 2387
2401 2388 .toggle-ajax-spinner{
2402 2389 height: 16px;
2403 2390 width: 16px;
2404 2391 }
2405 2392
2406 2393
2407 2394 .markup-form .clearfix {
2408 2395 .border-radius(@border-radius);
2409 2396 margin: 0px;
2410 2397 }
2411 2398
2412 2399 .markup-form-area {
2413 2400 padding: 8px 12px;
2414 2401 border: 1px solid @grey4;
2415 2402 .border-radius(@border-radius);
2416 2403 }
2417 2404
2418 2405 .markup-form-area-header .nav-links {
2419 2406 display: flex;
2420 2407 flex-flow: row wrap;
2421 2408 -webkit-flex-flow: row wrap;
2422 2409 width: 100%;
2423 2410 }
2424 2411
2425 2412 .markup-form-area-footer {
2426 2413 display: flex;
2427 2414 }
2428 2415
2429 2416 .markup-form-area-footer .toolbar {
2430 2417
2431 2418 }
2432 2419
2433 2420 // markup Form
2434 2421 div.markup-form {
2435 2422 margin-top: 20px;
2436 2423 }
2437 2424
2438 2425 .markup-form strong {
2439 2426 display: block;
2440 2427 margin-bottom: 15px;
2441 2428 }
2442 2429
2443 2430 .markup-form textarea {
2444 2431 width: 100%;
2445 2432 height: 100px;
2446 2433 font-family: 'Monaco', 'Courier', 'Courier New', monospace;
2447 2434 }
2448 2435
2449 2436 form.markup-form {
2450 2437 margin-top: 10px;
2451 2438 margin-left: 10px;
2452 2439 }
2453 2440
2454 2441 .markup-form .comment-block-ta,
2455 2442 .markup-form .preview-box {
2456 2443 .border-radius(@border-radius);
2457 2444 .box-sizing(border-box);
2458 2445 background-color: white;
2459 2446 }
2460 2447
2461 2448 .markup-form .preview-box.unloaded {
2462 2449 height: 50px;
2463 2450 text-align: center;
2464 2451 padding: 20px;
2465 2452 background-color: white;
2466 2453 }
@@ -1,696 +1,692 b''
1 1 // navigation.less
2 2 // For use in RhodeCode applications;
3 3 // see style guide documentation for guidelines.
4 4
5 5 // HEADER NAVIGATION
6 6
7 7 .horizontal-list {
8 8 float: right;
9 9 display: block;
10 10 margin: 0;
11 11 padding: 0;
12 12 -webkit-padding-start: 0;
13 13 text-align: left;
14 14 font-size: @navigation-fontsize;
15 15 color: @grey6;
16 16 z-index:10;
17 17
18 18 li {
19 19 line-height: 1em;
20 20 list-style-type: none;
21 21
22 22 a {
23 23 padding: 0 .5em;
24 24
25 25 &.menu_link_notifications {
26 26 .pill(7px,@rcblue);
27 27 display: inline;
28 28 margin: 0 7px 0 .7em;
29 29 font-size: @basefontsize;
30 30 color: white;
31 31
32 32 &.empty {
33 33 background-color: @grey4;
34 34 }
35 35
36 36 &:hover {
37 37 background-color: @rcdarkblue;
38 38 }
39 39 }
40 40 }
41 41 .pill_container {
42 42 margin: 1.25em 0px 0px 0px;
43 43 float: right;
44 44 }
45 45
46 46 &#quick_login_li {
47 47 &:hover {
48 48 color: @grey5;
49 49 }
50 50
51 51 a.menu_link_notifications {
52 52 color: white;
53 53 }
54 54
55 55 .user {
56 56 padding-bottom: 10px;
57 57 }
58 58
59 59 &.open {
60 60 .user {
61 61 border-bottom: 5px solid @rcblue;
62 62 }
63 63 }
64 64 }
65 65
66 66 &:before { content: none; }
67 67
68 68 &:last-child {
69 69 .menulabel {
70 70 padding-right: 0;
71 71 border-right: none;
72 72
73 73 .show_more {
74 74 padding-right: 0;
75 75 }
76 76 }
77 77
78 78 &> a {
79 79 border-bottom: none;
80 80 }
81 81 }
82 82
83 83 &.active {
84 84 border-bottom: 5px solid @rcblue;
85 85 }
86 86
87 87 &.open {
88 88
89 89 a {
90 90 color: white;
91 91 }
92 92 }
93 93
94 94 &:focus {
95 95 outline: none;
96 96 }
97 97
98 98 ul li {
99 99 display: block;
100 100
101 101 &:last-child> a {
102 102 border-bottom: none;
103 103 }
104 104
105 105 ul li:last-child a {
106 106 /* we don't expect more then 3 levels of submenu and the third
107 107 level can have different html structure */
108 108 border-bottom: none;
109 109 }
110 110 }
111 111 }
112 112
113 113 > li {
114 114 float: left;
115 115 display: block;
116 116 padding: 0;
117 117
118 118 > a,
119 119 &.has_select2 a {
120 120 display: block;
121 121 padding: 10px 0 2px;
122
123 .show_more {
124 margin-top: -4px;
125 padding-right: .5em;
126 }
127 122 }
128 123
129 124 .menulabel {
130 125 padding: 0 .5em;
131 126 line-height: 1em;
132 127 // for this specifically we do not use a variable
133 128 border-right: 1px solid @grey4;
134 129 }
135 130
136 131 .pr_notifications {
137 132 padding-left: .5em;
138 133 }
139 134
140 135 .pr_notifications + .menulabel {
141 136 display:inline;
142 137 padding-left: 0;
143 138 }
144 139
145 140 &:hover,
146 141 &.open,
147 142 &.active {
148 143 a {
149 144 color: @grey1;
150 145 }
151 146 }
152 147 }
153 148
154 149 pre {
155 150 margin: 0;
156 151 padding: 0;
157 152 }
158 153
159 154 .select2-container,
160 155 .menulink.childs {
161 156 position: relative;
162 157 }
163 158
164 159 #quick_login {
165 160
166 161 li a {
167 162 padding: .5em 0;
168 163 border-bottom: none;
169 164 color: @grey2;
170 165
171 166 &:hover { color: @grey1; }
172 167 }
173
174 .show_more {
175 padding-left: .5em;
176 }
177 168 }
178 169
179 170 #quick_login_link {
180 171 display: inline-block;
181 172
182 173 .gravatar {
183 border: 1px solid @grey2;
174 border: 1px solid @grey5;
184 175 }
185 176
186 177 .gravatar-login {
187 178 height: 20px;
188 179 width: 20px;
189 180 margin: -8px 0;
190 181 padding: 0;
191 182 }
192 183
193 184 &:hover .user {
194 185 color: @grey6;
195 186 }
196 187 }
197 188 }
198 189 .header .horizontal-list {
199 190
200 191 li {
201 192
202 193 &#quick_login_li {
203 194 padding-left: .5em;
204 195
205 196 &:hover #quick_login_link {
206 197 color: inherit;
207 198 }
199
200 .menu_link_user {
201 padding: 0 2px;
202 }
208 203 }
209 204
210 205 &:before { content: none; }
211 206 }
212 207
213 208 > li {
214 209
215 210 a {
216 211 padding: 18px 0 12px 0;
217 212 color: @nav-grey;
218 213
219 214 &.menu_link_notifications {
220 215 padding: 1px 8px;
221 216 }
222 217 }
223 218
224 219 &:hover,
225 220 &.open,
226 221 &.active {
227 222 .pill_container a {
228 223 // don't select text for the pill container, it has it' own
229 224 // hover behaviour
230 225 color: @nav-grey;
231 226 }
232 227 }
233 228
234 229 &:hover,
235 230 &.open,
236 231 &.active {
237 232 a {
238 233 color: @grey6;
239 234 }
240 235 }
241 236
242 237 .select2-dropdown-open a {
243 238 color: @grey6;
244 239 }
245 240
246 241 .repo-switcher {
247 242 padding-left: 0;
248 243
249 244 .menulabel {
250 245 padding-left: 0;
251 246 }
252 247 }
253 248 }
254 249
255 250 li ul li {
256 251 background-color:@grey2;
257 252
258 253 a {
259 254 padding: .5em 0;
260 255 border-bottom: @border-thickness solid @border-default-color;
261 256 color: @grey6;
262 257 }
263 258
264 259 &:last-child a, &.last a{
265 260 border-bottom: none;
266 261 }
267 262
268 263 &:hover {
269 264 background-color: @grey3;
270 265 }
271 266 }
272 267
273 268 .submenu {
274 269 margin-top: 5px;
275 270 }
276 271 }
277 272
278 273 // SUBMENUS
279 274 .navigation .submenu {
280 275 display: none;
281 276 }
282 277
283 278 .navigation li.open {
284 279 .submenu {
285 280 display: block;
286 281 }
287 282 }
288 283
289 284 .navigation li:last-child .submenu {
290 285 right: -20px;
291 286 left: auto;
292 287 }
293 288
294 289 .submenu {
295 290 position: absolute;
296 291 top: 100%;
297 292 left: 0;
298 293 min-width: 150px;
299 294 margin: 6px 0 0;
300 295 padding: 0;
301 296 text-align: left;
302 297 font-family: @text-light;
303 298 border-radius: @border-radius;
304 299 z-index: 20;
305 300
306 301 li {
307 302 display: block;
308 303 margin: 0;
309 304 padding: 0 .5em;
310 305 line-height: 1em;
311 306 color: @grey3;
312 307 background-color: @grey6;
313 308
314 309 &:before { content: none; }
315 310
316 311 a {
317 312 display: block;
318 313 width: 100%;
319 314 padding: .5em 0;
320 315 border-right: none;
321 316 border-bottom: @border-thickness solid white;
322 317 color: @grey3;
323 318 }
324 319
325 320 ul {
326 321 display: none;
327 322 position: absolute;
328 323 top: 0;
329 324 right: 100%;
330 325 padding: 0;
331 326 z-index: 30;
332 327 }
333 328 &:hover {
334 329 background-color: @grey5;
335 330 -webkit-transition: background .3s;
336 331 -moz-transition: background .3s;
337 332 -o-transition: background .3s;
338 333 transition: background .3s;
339 334
340 335 ul {
341 336 display: block;
342 337 }
343 338 }
344 339 }
345 340 }
346 341
347 342
348 343
349 344
350 345 // repo dropdown
351 346 .quick_repo_menu {
352 347 width: 15px;
353 348 text-align: center;
354 349 position: relative;
355 350 cursor: pointer;
356 351
357 352 div {
358 353 overflow: visible !important;
359 354 }
360 355
361 356 &.sorting {
362 357 cursor: auto;
363 358 }
364 359
365 360 &:hover {
366 361 .menu_items_container {
367 362 position: absolute;
368 363 display: block;
369 364 }
370 365 .menu_items {
371 366 display: block;
372 367 }
373 368 }
374 369
375 370 i {
376 371 margin: 0;
377 372 color: @grey4;
378 373 }
379 374
380 375 .menu_items_container {
381 376 position: absolute;
382 377 top: 0;
383 378 left: 100%;
384 379 margin: 0;
385 380 padding: 0;
386 381 list-style: none;
387 382 background-color: @grey6;
388 383 z-index: 999;
389 384 text-align: left;
390 385
391 386 a {
392 387 color: @grey2;
393 388 }
394 389
395 390 ul.menu_items {
396 391 margin: 0;
397 392 padding: 0;
398 393 }
399 394
400 395 li {
401 396 margin: 0;
402 397 padding: 0;
403 398 line-height: 1em;
404 399 list-style-type: none;
405 400
406 401 &:before { content: none; }
407 402
408 403 a {
409 404 display: block;
410 405 height: 16px;
411 406 padding: 8px; //must add up to td height (28px)
412 407 width: 120px; // set width
413 408
414 409 &:hover {
415 410 background-color: @grey5;
416 411 -webkit-transition: background .3s;
417 412 -moz-transition: background .3s;
418 413 -o-transition: background .3s;
419 414 transition: background .3s;
420 415 }
421 416 }
422 417 }
423 418 }
424 419 }
425 420
426 421 // Header Repository Switcher
427 422 // Select2 Dropdown
428 423 #select2-drop.select2-drop.repo-switcher-dropdown {
429 424 width: auto !important;
430 425 margin-top: 5px;
431 426 padding: 1em 0;
432 427 text-align: left;
433 428 .border-radius-bottom(@border-radius);
434 429 border-color: transparent;
435 430 color: @grey6;
436 431 background-color: @grey2;
437 432
438 433 input {
439 434 min-width: 90%;
440 435 }
441 436
442 437 ul.select2-result-sub {
443 438
444 439 li {
445 440 line-height: 1em;
446 441
447 442 &:hover,
448 443 &.select2-highlighted {
449 444 background-color: @grey3;
450 445 }
451 446 }
452 447
453 448 &:before { content: none; }
454 449 }
455 450
456 451 ul.select2-results {
457 452 min-width: 200px;
458 453 margin: 0;
459 454 padding: 0;
460 455 list-style-type: none;
461 456 overflow-x: visible;
462 457 overflow-y: scroll;
463 458
464 459 li {
465 460 padding: 0 8px;
466 461 line-height: 1em;
467 462 color: @grey6;
468 463
469 464 &:before { content: none; }
470 465
471 466 &>.select2-result-label {
472 467 padding: 8px 0;
473 468 border-bottom: @border-thickness solid @grey3;
474 469 white-space: nowrap;
475 470 color: @grey5;
476 471 cursor: pointer;
477 472 }
478 473
479 474 &.select2-result-with-children {
480 475 margin: 0;
481 476 padding: 0;
482 477 }
483 478
484 479 &.select2-result-unselectable > .select2-result-label {
485 480 margin: 0 8px;
486 481 }
487 482
488 483 }
489 484 }
490 485
491 486 ul.select2-result-sub {
492 487 margin: 0;
493 488 padding: 0;
494 489
495 490 li {
496 491 display: block;
497 492 margin: 0;
498 493 border-right: none;
499 494 line-height: 1em;
500 495 font-family: @text-light;
501 496 color: @grey2;
502 497
503 498 &:before { content: none; }
504 499
505 500 &:hover {
506 501 background-color: @grey3;
507 502 }
508 503 }
509 504 }
510 505 }
511 506
512 507
513 508 #context-bar {
514 509 display: block;
515 510 margin: 0 auto;
516 511 padding: 0 @header-padding;
517 512 background-color: @grey6;
518 513 border-bottom: @border-thickness solid @grey5;
519 514
520 515 .clear {
521 516 clear: both;
522 517 }
523 518 }
524 519
525 520 ul#context-pages {
526 521 li {
527 522 line-height: 1em;
528 523
529 524 &:before { content: none; }
530 525
531 526 a {
532 527 color: @grey3;
533 528 }
534 529
535 530 &.active {
536 531 // special case, non-variable color
537 532 border-bottom: 4px solid @nav-grey;
538 533
539 534 a {
540 535 color: @grey1;
541 536 }
542 537 }
543 538 }
544 539 }
545 540
546 541 // PAGINATION
547 542
548 543 .pagination {
549 544 border: @border-thickness solid @rcblue;
550 545 color: @rcblue;
551 546
552 547 .current {
553 548 color: @grey4;
554 549 }
555 550 }
556 551
557 552 .dataTables_processing {
558 553 text-align: center;
559 554 font-size: 1.1em;
560 555 position: relative;
561 556 top: 95px;
562 557 }
563 558
564 559 .dataTables_paginate, .pagination-wh {
565 560 text-align: left;
566 561 display: inline-block;
567 562 border-left: 1px solid @rcblue;
568 563 float: none;
569 564 overflow: hidden;
570 565
571 566 .paginate_button, .pager_curpage,
572 567 .pager_link, .pg-previous, .pg-next, .pager_dotdot {
573 568 display: inline-block;
574 569 padding: @menupadding/4 @menupadding;
575 570 border: 1px solid @rcblue;
576 571 border-left: 0;
577 572 color: @rcblue;
578 573 cursor: pointer;
579 574 float: left;
580 575 }
581 576
582 577 .pager_curpage, .pager_dotdot,
583 578 .paginate_button.current, .paginate_button.disabled,
584 579 .disabled {
585 580 color: @grey3;
586 581 cursor: default;
587 582 }
588 583
589 584 .ellipsis {
590 585 display: inline-block;
591 586 text-align: left;
592 587 padding: @menupadding/4 @menupadding;
593 588 border: 1px solid @rcblue;
594 589 border-left: 0;
595 590 float: left;
596 591 }
597 592 }
598 593
599 594 // SIDEBAR
600 595
601 596 .sidebar {
602 597 .block-left;
603 598 clear: left;
604 599 max-width: @sidebar-width;
605 600 margin-right: @sidebarpadding;
606 601 padding-right: @sidebarpadding;
607 602 font-family: @text-regular;
608 603 color: @grey1;
609 604
610 605 &#graph_nodes {
611 606 clear:both;
612 607 width: auto;
613 608 margin-left: -100px;
614 609 padding: 0;
615 610 border: none;
616 611 }
617 612
618 613 .nav-pills {
619 614 margin: 0;
620 615 }
621 616
622 617 .nav {
623 618 list-style: none;
624 619 padding: 0;
625 620
626 621 li {
627 622 padding-bottom: @menupadding;
628 623 line-height: 1em;
629 624 color: @grey4;
630 625
631 626 &.active a {
632 627 color: @grey2;
633 628 }
634 629
635 630 a {
636 631 color: @grey4;
637 632 }
638 633
639 634 &:before { content: none; }
640 635 }
641 636
642 637 }
643 638 }
644 639
645 640 .main_filter_help_box {
646 641 padding: 7px 7px;
647 642 border-top: 1px solid @grey4;
648 643 border-right: 1px solid @grey4;
649 644 border-bottom: 1px solid @grey4;
650 645 display: inline-block;
651 646 vertical-align: top;
652 margin-left: -5px;
647 margin-left: -7px;
653 648 background: @grey3;
654 649 }
655 650
656 651 .main_filter_input_box {
657 652 display: inline-block;
658 653 }
659 654
660 655 .main_filter_box {
661 656 margin: 9px 0 0 0;
662 657 }
663 658
664 659 #main_filter_help {
665 660 background: @grey3;
666 661 border: 1px solid black;
667 662 position: absolute;
668 663 white-space: pre-wrap;
669 664 z-index: 9999;
670 665 color: @nav-grey;
671 666 margin: 1px 7px;
672 667 padding: 0 2px;
673 668 }
674 669
675 670 .main_filter_input {
676 padding: 6px;
671 padding: 5px;
677 672 min-width: 220px;
678 673 color: @nav-grey;
679 674 background: @grey3;
675 min-height: 18px;
680 676 }
681 677
682 678 .main_filter_input::placeholder {
683 679 color: @nav-grey;
684 680 opacity: 1;
685 681 }
686 682
687 683 .notice-box {
688 684 display:block !important;
689 685 padding: 9px 0 !important;
690 686 }
691 687
692 688 .menulabel-notice {
693 689 border: 1px solid @color5;
694 690 padding:7px 10px;
695 691 color: @color5;
696 692 }
@@ -1,167 +1,170 b''
1 1 @font-face {
2 2 font-family: 'rcicons';
3 3 src: url('../fonts/RCIcons/rcicons.eot?74666722');
4 4 src: url('../fonts/RCIcons/rcicons.eot?74666722#iefix') format('embedded-opentype'),
5 5 url('../fonts/RCIcons/rcicons.woff2?74666722') format('woff2'),
6 6 url('../fonts/RCIcons/rcicons.woff?74666722') format('woff'),
7 7 url('../fonts/RCIcons/rcicons.ttf?74666722') format('truetype'),
8 8 url('../fonts/RCIcons/rcicons.svg?74666722#rcicons') format('svg');
9 9 font-weight: normal;
10 10 font-style: normal;
11 11 }
12 12 /* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
13 13 /* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
14 14 /*
15 15 @media screen and (-webkit-min-device-pixel-ratio:0) {
16 16 @font-face {
17 17 font-family: 'rcicons';
18 18 src: url('../fonts/RCIcons/rcicons.svg?74666722#rcicons') format('svg');
19 19 }
20 20 }
21 21 */
22 22
23 23 [class^="icon-"]:before, [class*=" icon-"]:before {
24 24 font-family: "rcicons";
25 25 font-style: normal;
26 26 font-weight: normal;
27 27 speak: none;
28 28
29 29 display: inline-block;
30 30 text-decoration: inherit;
31 31 width: 1em;
32 32 margin-right: .2em;
33 33 text-align: center;
34 34 /* opacity: .8; */
35 35
36 36 /* For safety - reset parent styles, that can break glyph codes*/
37 37 font-variant: normal;
38 38 text-transform: none;
39 39
40 40 /* fix buttons height, for twitter bootstrap */
41 41 line-height: 1em;
42 42
43 43 /* Animation center compensation - margins should be symmetric */
44 44 /* remove if not needed */
45 45 margin-left: .2em;
46 46
47 47 /* you can be more comfortable with increased icons size */
48 48 /* font-size: 120%; */
49 49
50 50 /* Font smoothing. That was taken from TWBS */
51 51 -webkit-font-smoothing: antialiased;
52 52 -moz-osx-font-smoothing: grayscale;
53 53
54 54 /* Uncomment for 3D effect */
55 55 /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
56 56 }
57 57
58 58 .icon-no-margin::before {
59 59 margin: 0;
60 60
61 61 }
62 62 // -- ICON CLASSES -- //
63 63
64 64 .icon-bookmark:before { content: '\e803'; } /* '' */
65 65 .icon-branch:before { content: '\e804'; } /* '' */
66 66 .icon-lock:before { content: '\e806'; } /* '' */
67 67 .icon-unlock:before { content: '\e807'; } /* '' */
68 68 .icon-delete:before { content: '\e808'; } /* '' */
69 69 .icon-false:before { content: '\e808'; } /* '' */
70 70
71 71 .icon-ok:before { content: '\e809'; } /* '' */
72 72 .icon-true:before { content: '\e809'; } /* '' */
73 73
74 74 .icon-comment:before { content: '\e80a'; } /* '' */
75 75 .icon-comment-add:before { content: '\e816'; } /* '' */
76 76 .icon-comment_toggle:before { content: '\e818'; } /* '' */
77 77
78 78 .icon-feed:before { content: '\e80b'; } /* '' */
79 79
80 80 .icon-right:before { content: '\e80c'; } /* '' */
81 81 .icon-left:before { content: '\e80d'; } /* '' */
82 82
83 83 .icon-arrow_down:before { content: '\e80e'; } /* '' */
84 84 .icon-arrow_up:before { content: '\e80e'; } /* '' */
85 85
86 86 .icon-group:before { content: '\e812'; } /* '' */
87 87
88 88 .icon-fork:before { content: '\e814'; } /* '' */
89 89 .icon-merge:before { content: '\e814'; } /* '' */
90 90
91 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 96 .icon-git-inv:before { content: '\e80f'; } /* '' */
94 97 .icon-hg-inv:before { content: '\e810'; } /* '' */
95 98 .icon-svn-inv:before { content: '\e811'; } /* '' */
96 99
97 100 .icon-git:before { content: '\e81a'; } /* '' */
98 101 .icon-hg:before { content: '\e81b'; } /* '' */
99 102 .icon-svn:before { content: '\e820'; } /* '' */
100 103
101 104 .icon-minus:before { content: '\e81c'; } /* '' */
102 105 .icon-plus:before { content: '\e81d'; } /* '' */
103 106 .icon-remove:before { content: '\e81e'; } /* '' */
104 107 .icon-remove-sign:before { content: '\e81e'; } /* '' */
105 108
106 109 .icon-rhodecode:before { content: '\e81f'; } /* '' */
107 110
108 111 .icon-tag:before { content: '\e821'; } /* '' */
109 112 .icon-copy:before { content: '\f0c5'; } /* '' */
110 113 .icon-clipboard:before { content: '\f0c5'; } /* '' */
111 114
112 115
113 116 .icon-folder:before { content: '\e813'; } /* '' */
114 117 .icon-folder-close:before { content: '\e813'; } /* '' */
115 118
116 119 .icon-directory:before { content: '\e800'; } /* '' */
117 120 .icon-directory-empty:before { content: '\f114'; } /* '' */
118 121 .icon-file-text:before { content: '\f0f6'; } /* '' */
119 122 .icon-file-text-inv:before { content: '\f15c'; } /* '' */
120 123 .icon-file-code:before { content: '\f1c9'; } /* '' */
121 124
122 125 // MERGED ICONS
123 126
124 127 .icon-repo-private:before { &:extend(.icon-lock:before); }
125 128 .icon-repo-lock:before { &:extend(.icon-lock:before); }
126 129 .icon-unlock-alt:before { &:extend(.icon-unlock:before); }
127 130 .icon-repo-unlock:before { &:extend(.icon-unlock:before); }
128 131 .icon-repo-public:before { &:extend(.icon-unlock:before); }
129 132 .icon-rss-sign:before { &:extend(.icon-feed:before); }
130 133 .icon-code-fork:before { &:extend(.icon-fork:before); }
131 134
132 135 // TRANSFORM
133 136 .icon-arrow_up:before {transform: rotate(180deg);}
134 137 .icon-merge:before {transform: rotate(180deg);}
135 138
136 139 // -- END ICON CLASSES -- //
137 140
138 141
139 142 //--- ICONS STYLING ------------------//
140 143
141 144 .icon-git { color: @color4 !important; }
142 145 .icon-hg { color: @color8 !important; }
143 146 .icon-svn { color: @color1 !important; }
144 147 .icon-git-inv { color: @color4 !important; }
145 148 .icon-hg-inv { color: @color8 !important; }
146 149 .icon-svn-inv { color: @color1 !important; }
147 150 .icon-repo-lock { color: #FF0000; }
148 151 .icon-repo-unlock { color: #FF0000; }
149 152
150 153 .repo-switcher-dropdown .select2-result-label {
151 154 .icon-git:before {
152 155 &:extend(.icon-git-transparent:before);
153 156 }
154 157 .icon-hg:before {
155 158 &:extend(.icon-hg-transparent:before);
156 159 color: @alert4;
157 160 }
158 161 .icon-svn:before {
159 162 &:extend(.icon-svn-transparent:before);
160 163 }
161 164 }
162 165
163 166 .icon-user-group:before {
164 167 &:extend(.icon-group:before);
165 168 margin: 0;
166 169 font-size: 16px;
167 170 }
@@ -1,222 +1,222 b''
1 1 // select2.less
2 2 // For use in RhodeCode application drop down select boxes;
3 3 // see style guide documentation for guidelines.
4 4
5 5
6 6 // SELECT2 DROPDOWN MENUS
7 7
8 8 //Select2 Dropdown
9 9 .select2-results{
10 10 .box-sizing(border-box);
11 11 overflow-y: scroll;
12 12 }
13 13
14 14 .select2-container{margin: 0; position: relative; display: inline-block; zoom: 1;}
15 15 .select2-container,
16 16 .select2-drop,
17 17 .select2-search,
18 18 .select2-search input {.box-sizing(border-box);}
19 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 20 .main .select2-container .select2-choice { background-color: white; }
21 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 22 .select2-container.select2-allowclear .select2-choice abbr {display: inline-block;}
23 23 .select2-container .select2-choice abbr:hover { background-position: right -11px; cursor: pointer; }
24 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 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 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 27 .select2-drop-active { border: @border-thickness solid #5897fb; border-top: none; }
28 28 .select2-drop.select2-drop-above.select2-drop-active {border-top: @border-thickness solid #5897fb;}
29 29 .select2-drop-auto-width { border-top: @border-thickness solid #aaa; width: auto; }
30 30 .select2-drop-auto-width .select2-search {padding-top: 4px;}
31 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 32 html[dir="rtl"] .select2-container .select2-choice .select2-arrow b {background-position: 2px 1px;}
33 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 34 .select2-search input { width: 100%; height: auto !important; min-height: 26px; padding: 4px 20px 4px 5px; margin: 0; outline: 0; }
35 35 html[dir="rtl"] .select2-search input { padding: 4px 5px 4px 20px; background: #fff url('../images/select2.png') no-repeat -37px -22px; }
36 36 .select2-drop.select2-drop-above .select2-search input {margin-top: 4px;}
37 37 .select2-dropdown-open .select2-choice .select2-arrow { background: transparent; border-left: none; filter: none; }
38 38 html[dir="rtl"] .select2-dropdown-open .select2-choice .select2-arrow {border-right: none;}
39 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 40 /* results */
41 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 42 html[dir="rtl"] .select2-results { padding: 0 4px 0 0; margin: 4px 0 4px 4px; }
43 43 .select2-results .select2-disabled{background:@grey6;display:list-item;cursor:default}
44 44 .select2-results .select2-selected{display:none}
45 45 .select2-more-results.select2-active{background:#f4f4f4 url('../images/select2-spinner.gif') no-repeat 100%}
46 46 .select2-container.select2-container-disabled .select2-choice abbr{display:none}
47 47 .select2-container.select2-container-disabled {background:@grey6;cursor:default}
48 48 .select2-container.select2-container-disabled .select2-choice {background:@grey6;cursor:default}
49 49 .select2-container-multi .select2-choices li{float:left;list-style:none}
50 50 .select2-container-multi .select2-choices .select2-search-field{margin:0;padding:0;white-space:nowrap}
51 51 .select2-container-multi .select2-choices .select2-search-choice .select2-chosen{cursor:default}
52 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 53 .select2-container-multi .select2-search-choice-close{left:3px}
54 54 .select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover{background-position:right -11px}
55 55 .select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close{background-position:right -11px}
56 56 .select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close{display:none;background:none}
57 57 .select2-offscreen,.select2-offscreen:focus{clip:rect(0 0 0 0) !important;width:1px !important;height:1px !important;
58 58 border:0 !important;margin:0 !important;padding:0 !important;overflow:hidden !important;
59 59 position: absolute !important;outline:0 !important;left:0 !important;top:0 !important}
60 60 .select2-display-none,
61 61 .select2-search-hidden {display:none}
62 62 .select2-search input { border-color: @rclightblue; }
63 63
64 64 .select2-measure-scrollbar{position:absolute;top:-10000px;left:-10000px;width:100px;height:100px;overflow:scroll}
65 65 @media only screen and (-webkit-min-device-pixel-ratio:1.5),
66 66 only screen and (min-resolution:144dpi){
67 67 .select2-search input,
68 68 .select2-search-choice-close,
69 69 .select2-container .select2-choice abbr,
70 70 .select2-container .select2-choice .select2-arrow b{background-image:url('../images/select2x2.png');background-repeat:no-repeat;background-size:60px 40px;}
71 71 .select2-search input{background-position:100% -21px}
72 72 }
73 73 [class^="input-"] [class^="select2-choice"]>div{display:none}
74 74 [class^="input-"] .select2-offscreen{position:absolute}
75 75 select.select2{height:28px;visibility:hidden}
76 76 .autocomplete-suggestions{overflow:auto}
77 77 .autocomplete-suggestion{white-space:nowrap;overflow:hidden}
78 78
79 79 /* Retina-ize icons */
80 80 @media only screen and (-webkit-min-device-pixel-ratio:1.5),
81 81 only screen and (min-resolution:144dpi){
82 82 .select2-search input,
83 83 .select2-search-choice-close,
84 84 .select2-container .select2-choice abbr,
85 85 .select2-container .select2-choice .select2-arrow b{background-image:url('../images/select2x2.png');background-repeat:no-repeat;background-size:60px 40px;}
86 86 .select2-search input{background-position:100% -21px}
87 87 }
88 88
89 89 //Internal Select2 Dropdown Menus
90 90
91 91 .drop-menu-core {
92 92 min-width: 160px;
93 93 margin: 0 @padding 0 0;
94 94 padding: 0;
95 95 border: @border-thickness solid @rcblue;
96 96 border-radius: @border-radius;
97 97 color: @rcblue;
98 98 background-color: white;
99 99 }
100 100
101 101 .drop-menu-dropdown {
102 102 .drop-menu-core;
103 103
104 104 .flag_status {
105 105 margin-top: 0;
106 106 }
107 107 }
108 108
109 109 .drop-menu-base {
110 110 .drop-menu-core;
111 111 position: relative;
112 112 display: inline-block;
113 113 line-height: 1em;
114 114 z-index: 2;
115 115 cursor: pointer;
116 116
117 117 .flag_status {
118 118 margin-top: 0;
119 119 }
120 120
121 121 a {
122 122 display:block;
123 123 padding: .9em;
124 124 padding-right: 2em;
125 125 position: relative;
126 126
127 127 &:after {
128 128 position: absolute;
129 129 content: "\00A0\25BE";
130 right: .6em;
130 right: .1em;
131 131 line-height: 1em;
132 top: 0.9em;
132 top: 0.4em;
133 133 width: 1em;
134 font-size: 1em;
134 font-size: 20px;
135 135 }
136 136 }
137 137 }
138 138
139 139 .drop-menu {
140 140 .drop-menu-base;
141 141 width: auto !important;
142 142 }
143 143
144 144 .drop-menu-no-width {
145 145 .drop-menu-base;
146 146 width: auto;
147 147 }
148 148
149 149 .field-sm .drop-menu {
150 150 padding: 1px 0 0 0;
151 151 a {
152 152 padding: 6px;
153 153 };
154 154 }
155 155
156 156 .select2-search input {
157 157 width: 100%;
158 158 margin: .5em 0;
159 159 padding: .5em;
160 160 }
161 161
162 162 .select2-no-results {
163 163 padding: .5em;
164 164 }
165 165
166 166 .drop-menu-dropdown ul {
167 167 width: auto;
168 168 margin: 0;
169 169 padding: 0;
170 170 z-index: 50;
171 171
172 172 li {
173 173 margin: 0;
174 174 line-height: 1em;
175 175 list-style-type: none;
176 176
177 177 &:before { content: none; }
178 178
179 179 &:hover,
180 180 &.select2-highlighted {
181 181 background-color: @rclightblue;
182 182 }
183 183
184 184 &.select2-result-with-children {
185 185 &:hover {
186 186 background-color: white;
187 187 }
188 188 }
189 189
190 190 .select2-result-label {
191 191 display:block;
192 192 padding: 8px;
193 193 font-family: @text-regular;
194 194 border-bottom: @border-thickness solid @rclightblue;
195 195 color: @rcblue;
196 196 cursor: pointer;
197 197 }
198 198 &.select2-result-with-children {
199 199
200 200 .select2-result-label {
201 201 font-family: @text-semibold;
202 202 color: @rcdarkblue;
203 203 cursor: default;
204 204 }
205 205
206 206 ul.select2-result-sub li .select2-result-label {
207 207 padding-left: 16px;
208 208 font-family: @text-regular;
209 209 color: @rcblue;
210 210 cursor: pointer;
211 211 }
212 212 }
213 213 }
214 214 }
215 215
216 216 .side-by-side-selector {
217 217 .left-group,
218 218 .middle-group,
219 219 .right-group {
220 220 margin-bottom: @padding;
221 221 }
222 222 }
@@ -1,545 +1,545 b''
1 1 //
2 2 // Typography
3 3 // modified from Bootstrap
4 4 // --------------------------------------------------
5 5
6 6 // Base
7 7 body {
8 8 font-size: @basefontsize;
9 9 font-family: @text-light;
10 10 letter-spacing: .02em;
11 11 color: @grey2;
12 12 }
13 13
14 14 #content, label{
15 15 font-size: @basefontsize;
16 16 }
17 17
18 18 label {
19 19 color: @grey2;
20 20 }
21 21
22 22 ::selection { background: @rchighlightblue; }
23 23
24 24 // Headings
25 25 // -------------------------
26 26
27 27 h1, h2, h3, h4, h5, h6,
28 28 .h1, .h2, .h3, .h4, .h5, .h6 {
29 29 margin: 0 0 @textmargin 0;
30 30 padding: 0;
31 31 line-height: 1.8em;
32 32 color: @text-color;
33 33 a {
34 34 color: @rcblue;
35 35 }
36 36 }
37 37
38 38 h1, .h1 { font-size: 1.54em; font-family: @text-bold; }
39 39 h2, .h2 { font-size: 1.23em; font-family: @text-semibold; }
40 40 h3, .h3 { font-size: 1.23em; font-family: @text-regular; }
41 41 h4, .h4 { font-size: 1em; font-family: @text-bold; }
42 42 h5, .h5 { font-size: 1em; font-family: @text-bold-italic; }
43 43 h6, .h6 { font-size: 1em; font-family: @text-bold-italic; }
44 44
45 45 // Breadcrumbs
46 46 .breadcrumbs {
47 &:extend(h1);
47 font-size: @repo-title-fontsize;
48 48 margin: 0;
49 49 }
50 50
51 51 .breadcrumbs_light {
52 52 float:left;
53 53 font-size: 1.3em;
54 54 line-height: 38px;
55 55 }
56 56
57 57 // Body text
58 58 // -------------------------
59 59
60 60 p {
61 61 margin: 0 0 @textmargin 0;
62 62 padding: 0;
63 63 line-height: 2em;
64 64 }
65 65
66 66 .lead {
67 67 margin-bottom: @textmargin;
68 68 font-weight: 300;
69 69 line-height: 1.4;
70 70
71 71 @media (min-width: @screen-sm-min) {
72 72 font-size: (@basefontsize * 1.5);
73 73 }
74 74 }
75 75
76 76 a,
77 77 .link {
78 78 color: @rcblue;
79 79 text-decoration: none;
80 80 outline: none;
81 81 cursor: pointer;
82 82
83 83 &:focus {
84 84 outline: none;
85 85 }
86 86
87 87 &:hover {
88 88 color: @rcdarkblue;
89 89 }
90 90 }
91 91
92 92 img {
93 93 border: none;
94 94 outline: none;
95 95 }
96 96
97 97 strong {
98 98 font-family: @text-bold;
99 99 }
100 100
101 101 em {
102 102 font-family: @text-italic;
103 103 }
104 104
105 105 strong em,
106 106 em strong {
107 107 font-family: @text-bold-italic;
108 108 }
109 109
110 110 //TODO: lisa: b and i are depreciated, but we are still using them in places.
111 111 // Should probably make some decision whether to keep or lose these.
112 112 b {
113 113
114 114 }
115 115
116 116 i {
117 117 font-style: normal;
118 118 }
119 119
120 120 label {
121 121 color: @text-color;
122 122
123 123 input[type="checkbox"] {
124 124 margin-right: 1em;
125 125 }
126 126 input[type="radio"] {
127 127 margin-right: 1em;
128 128 }
129 129 }
130 130
131 131 code,
132 132 .code {
133 133 font-size: .95em;
134 134 font-family: @text-code;
135 135 color: @grey3;
136 136
137 137 a {
138 138 color: lighten(@rcblue,10%)
139 139 }
140 140 }
141 141
142 142 pre {
143 143 margin: 0;
144 144 padding: 0;
145 145 border: 0;
146 146 outline: 0;
147 147 font-size: @basefontsize*.95;
148 148 line-height: 1.4em;
149 149 font-family: @text-code;
150 150 color: @grey3;
151 151 }
152 152
153 153 // Emphasis & misc
154 154 // -------------------------
155 155
156 156 small,
157 157 .small {
158 158 font-size: 75%;
159 159 font-weight: normal;
160 160 line-height: 1em;
161 161 }
162 162
163 163 mark,
164 164 .mark {
165 165 background-color: @rclightblue;
166 166 padding: .2em;
167 167 }
168 168
169 169 // Alignment
170 170 .text-left { text-align: left; }
171 171 .text-right { text-align: right; }
172 172 .text-center { text-align: center; }
173 173 .text-justify { text-align: justify; }
174 174 .text-nowrap { white-space: nowrap; }
175 175
176 176 // Transformation
177 177 .text-lowercase { text-transform: lowercase; }
178 178 .text-uppercase { text-transform: uppercase; }
179 179 .text-capitalize { text-transform: capitalize; }
180 180
181 181 // Contextual colors
182 182 .text-muted {
183 183 color: @grey4;
184 184 }
185 185 .text-primary {
186 186 color: @rcblue;
187 187 }
188 188 .text-success {
189 189 color: @alert1;
190 190 }
191 191 .text-info {
192 192 color: @alert4;
193 193 }
194 194 .text-warning {
195 195 color: @alert3;
196 196 }
197 197 .text-danger {
198 198 color: @alert2;
199 199 }
200 200
201 201 // Contextual backgrounds
202 202 .bg-primary {
203 203 background-color: white;
204 204 }
205 205 .bg-success {
206 206 background-color: @alert1;
207 207 }
208 208 .bg-info {
209 209 background-color: @alert4;
210 210 }
211 211 .bg-warning {
212 212 background-color: @alert3;
213 213 }
214 214 .bg-danger {
215 215 background-color: @alert2;
216 216 }
217 217
218 218
219 219 // Page header
220 220 // -------------------------
221 221
222 222 .page-header {
223 223 margin: @pagepadding 0 @textmargin;
224 224 border-bottom: @border-thickness solid @grey5;
225 225 }
226 226
227 227 .title {
228 228 clear: both;
229 229 float: left;
230 230 width: 100%;
231 231 margin: @pagepadding/2 0 @pagepadding;
232 232
233 .breadcrumbs{
233 .breadcrumbs {
234 234 float: left;
235 235 clear: both;
236 236 width: 700px;
237 237 margin: 0;
238 238
239 239 .q_filter_box {
240 240 margin-right: @padding;
241 241 }
242 242 }
243 243
244 244 h1 a {
245 245 color: @rcblue;
246 246 }
247 247
248 248 input{
249 249 margin-right: @padding;
250 250 }
251 251
252 252 h5, .h5 {
253 253 color: @grey1;
254 254 margin-bottom: @space;
255 255
256 256 span {
257 257 display: inline-block;
258 258 }
259 259 }
260 260
261 261 p {
262 262 margin-bottom: 0;
263 263 }
264 264
265 265 .links {
266 266 float: right;
267 267 display: inline;
268 268 margin: 0;
269 269 padding-left: 0;
270 270 list-style: none;
271 271 text-align: right;
272 272
273 273 li:before { content: none; }
274 274 li { float: right; }
275 275 a {
276 276 display: inline-block;
277 277 margin-left: @textmargin/2;
278 278 }
279 279 }
280 280
281 281 .title-content {
282 282 float: left;
283 283 margin: 0;
284 284 padding: 0;
285 285
286 286 & + .breadcrumbs {
287 287 margin-top: @padding;
288 288 }
289 289
290 290 & + .links {
291 291 margin-top: -@button-padding;
292 292
293 293 & + .breadcrumbs {
294 294 margin-top: @padding;
295 295 }
296 296 }
297 297 }
298 298
299 299 .title-main {
300 300 font-size: @repo-title-fontsize;
301 301 }
302 302
303 303 .title-description {
304 304 margin-top: .5em;
305 305 }
306 306
307 307 .q_filter_box {
308 308 width: 200px;
309 309 }
310 310
311 311 }
312 312
313 313 #readme .title {
314 314 text-transform: none;
315 315 }
316 316
317 317 // Lists
318 318 // -------------------------
319 319
320 320 // Unordered and Ordered lists
321 321 ul,
322 322 ol {
323 323 margin-top: 0;
324 324 margin-bottom: @textmargin;
325 325 ul,
326 326 ol {
327 327 margin-bottom: 0;
328 328 }
329 329 }
330 330
331 331 li {
332 332 line-height: 2em;
333 333 }
334 334
335 335 ul li {
336 336 position: relative;
337 337 display: block;
338 338 list-style-type: none;
339 339
340 340 &:before {
341 341 content: "\2014\00A0";
342 342 position: absolute;
343 343 top: 0;
344 344 left: -1.25em;
345 345 }
346 346
347 347 p:first-child {
348 348 display:inline;
349 349 }
350 350 }
351 351
352 352 // List options
353 353
354 354 // Unstyled keeps list items block level, just removes default browser padding and list-style
355 355 .list-unstyled {
356 356 padding-left: 0;
357 357 list-style: none;
358 358 li:before { content: none; }
359 359 }
360 360
361 361 // Inline turns list items into inline-block
362 362 .list-inline {
363 363 .list-unstyled();
364 364 margin-left: -5px;
365 365
366 366 > li {
367 367 display: inline-block;
368 368 padding-left: 5px;
369 369 padding-right: 5px;
370 370 }
371 371 }
372 372
373 373 // Description Lists
374 374
375 375 dl {
376 376 margin-top: 0; // Remove browser default
377 377 margin-bottom: @textmargin;
378 378 }
379 379
380 380 dt,
381 381 dd {
382 382 line-height: 1.4em;
383 383 }
384 384
385 385 dt {
386 386 margin: @textmargin 0 0 0;
387 387 font-family: @text-bold;
388 388 }
389 389
390 390 dd {
391 391 margin-left: 0; // Undo browser default
392 392 }
393 393
394 394 // Horizontal description lists
395 395 // Defaults to being stacked without any of the below styles applied, until the
396 396 // grid breakpoint is reached (default of ~768px).
397 397 // These are used in forms as well; see style guide.
398 398 // TODO: lisa: These should really not be used in forms.
399 399
400 400 .dl-horizontal {
401 401
402 402 overflow: hidden;
403 403 margin-bottom: @space;
404 404
405 405 dt, dd {
406 406 float: left;
407 407 margin: 5px 0 5px 0;
408 408 }
409 409
410 410 dt {
411 411 clear: left;
412 412 width: @label-width - @form-vertical-margin;
413 413 }
414 414
415 415 dd {
416 416 &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present
417 417 margin-left: @form-vertical-margin;
418 418 max-width: @form-max-width - (@label-width - @form-vertical-margin) - @form-vertical-margin;
419 419 }
420 420
421 421 pre {
422 422 margin: 0;
423 423 }
424 424
425 425 &.settings {
426 426 dt {
427 427 text-align: left;
428 428 }
429 429 }
430 430
431 431 @media (min-width: 768px) {
432 432 dt {
433 433 float: left;
434 434 width: 180px;
435 435 clear: left;
436 436 text-align: right;
437 437 }
438 438 dd {
439 439 margin-left: 20px;
440 440 }
441 441 }
442 442 }
443 443
444 444
445 445 // Misc
446 446 // -------------------------
447 447
448 448 // Abbreviations and acronyms
449 449 abbr[title],
450 450 abbr[data-original-title] {
451 451 cursor: help;
452 452 border-bottom: @border-thickness dotted @grey4;
453 453 }
454 454 .initialism {
455 455 font-size: 90%;
456 456 text-transform: uppercase;
457 457 }
458 458
459 459 // Blockquotes
460 460 blockquote {
461 461 padding: 1em 2em;
462 462 margin: 0 0 2em;
463 463 font-size: @basefontsize;
464 464 border-left: 2px solid @grey6;
465 465
466 466 p,
467 467 ul,
468 468 ol {
469 469 &:last-child {
470 470 margin-bottom: 0;
471 471 }
472 472 }
473 473
474 474 footer,
475 475 small,
476 476 .small {
477 477 display: block;
478 478 font-size: 80%;
479 479
480 480 &:before {
481 481 content: '\2014 \00A0'; // em dash, nbsp
482 482 }
483 483 }
484 484 }
485 485
486 486 // Opposite alignment of blockquote
487 487 //
488 488 .blockquote-reverse,
489 489 blockquote.pull-right {
490 490 padding-right: 15px;
491 491 padding-left: 0;
492 492 border-right: 5px solid @grey6;
493 493 border-left: 0;
494 494 text-align: right;
495 495
496 496 // Account for citation
497 497 footer,
498 498 small,
499 499 .small {
500 500 &:before { content: ''; }
501 501 &:after {
502 502 content: '\00A0 \2014'; // nbsp, em dash
503 503 }
504 504 }
505 505 }
506 506
507 507 // Addresses
508 508 address {
509 509 margin-bottom: 2em;
510 510 font-style: normal;
511 511 line-height: 1.8em;
512 512 }
513 513
514 514 .error-message {
515 515 display: block;
516 516 margin: @padding/3 0;
517 517 color: @alert2;
518 518 }
519 519
520 520 .issue-tracker-link {
521 521 color: @rcblue;
522 522 }
523 523
524 524 .info_text{
525 525 font-size: @basefontsize;
526 526 color: @grey4;
527 527 font-family: @text-regular;
528 528 }
529 529
530 530 // help block text
531 531 .help-block {
532 532 display: block;
533 533 margin: 0 0 @padding;
534 534 color: @grey4;
535 535 font-family: @text-light;
536 536 &.pre-formatting {
537 537 white-space: pre;
538 538 }
539 539 }
540 540
541 541 .error-message {
542 542 display: block;
543 543 margin: @padding/3 0;
544 544 color: @alert2;
545 545 }
@@ -1,138 +1,138 b''
1 1 // variables for use in all RhodeCode products
2 2
3 3 // FONTS
4 4 //Primary Colors (brand)
5 5 @rcblue: #427cc9; //RhodeCode blue
6 6 @rcdarkblue: #305b91; //RhodeCode dark blue
7 7 @rclightblue: lighten(@rcblue, 30%);
8 8 @rchighlightblue: lighten(@rcblue, 35%);
9 9
10 10 // Secondary Colors (greyscale)
11 11 @grey1: #202020; //midnight
12 12 @grey2: #323232; //charcoal
13 13 @grey3: #666666; //tungsten
14 14 @grey4: #979797; //light grey
15 15 @grey5: #dbd9da; //greyish
16 16 @grey6: #eeeeee; //silver
17 17 @grey7: #f9f9f9; //light silver
18 18
19 19 // special for navigation
20 20 @nav-grey: #CDCCCD;
21 21
22 22 @grey5-alpha: rgba(219, 217, 218, 0.3);
23 23
24 24 // Tertiary Colors
25 25 @color1: #879938; //olive green
26 26 @color2: #fcc93a; //bright yellow
27 27 @color3: #ff9e07; //orange-yellow
28 28 @color4: #fc663a; //bright orange
29 29 @color5: #d63d44; //signal red
30 30 @color6: #99287c; //violet
31 31 @color7: #682668; //dark purple
32 32 @color8: #194f8e; //dark blue
33 33
34 34 // Alert Colors (bright)
35 35 @alert1: #0ac878; //bright green
36 36 @alert2: #e85e4d; //soft red
37 37 @alert3: #ffc854; //corn yellow
38 38 @alert4: #84a5d2; //light blue
39 39
40 40 // Alert Inner Colors
41 41 @alert1-inner: #daf7eb; //bright green
42 42 @alert2-inner: #fbdfdb; //soft red
43 43 @alert3-inner: #fff4dd; //corn yellow
44 44 @alert4-inner: #e6edf6; //light blue
45 45
46 46 // Highlight color for lines and colors
47 47 @comment-highlight-color: #ffd887;
48 48
49 49 // FONTS
50 50 @basefontsize: 13px;
51 51 @navigation-fontsize: 14px;
52 52 @journal-fontsize: @basefontsize+7px;
53 53 @text-color: @grey2;
54 54 @repo-title-fontsize: 18px;
55 55
56 @text-regular: "proximanovaregular","Proxima Nova Regular", "Proxima Nova", sans-serif;
57 @text-italic: "proximanovaitalic","Proxima Nova Italic", "Proxima Nova", sans-serif;
58 @text-bold: "proximanovabold","Proxima Nova Bold", "Proxima Nova", sans-serif;
59 @text-semibold: "proximanovasemibold","Proxima Nova Semibold", "Proxima Nova", sans-serif;
60 @text-bold-italic: "proximanovabolditalic","Proxima Nova Bold Italic", "Proxima Nova", sans-serif;
61 @text-code: "Lucida Console", Menlo, Monaco, monospace;
56 @text-regular: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
57 @text-italic: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
58 @text-bold: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
59 @text-semibold: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
60 @text-bold-italic: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
61 @text-code: 'Menlo', 'Liberation Mono', 'Consolas', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Courier New', 'andale mono', 'lucida console', monospace;
62 62 @text-light: @text-regular;
63 63 @text-light-italic: @text-italic;
64 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 67 @panel-title: @basefontsize;
68 68 @panel-footer: @basefontsize;
69 69
70 70 // BORDERS
71 71 @border-thickness: 1px;
72 72 @border-thickness-buttons: 1px;
73 73 @border-thickness-tags: 1px;
74 74 @border-radius: 2px;
75 75 @border-default-color: @grey5;
76 76 @border-highlight-color: @grey4;
77 77
78 78 // SPACING
79 79 @contentpadding: 15px; //padding on left and right of pages
80 80 @pagepadding: 40px; //padding on top and bottom of pages
81 81 @menupadding: 12px; //padding for sidebar and content
82 82 @sidebarpadding: 15px; //spacing between sections
83 83 @space: 40px; //spacing between sections
84 84 @padding: 15px; //padding inside modules
85 85 @textmargin: 20px; //spacing below headers
86 86 @header-padding: 20px;
87 87 @panel-padding: @padding;
88 88 @gravatar-size: 16px; // height/width of gravatar w/o border
89 89
90 90 // ADMIN
91 91 @form-max-width: 750px;
92 92
93 93 // FORMS (new)
94 94 @border-thickness-inputs: 1px;
95 95 @input-padding: @button-padding; //needs to match button padding
96 96 // TODO: johbo: Needed for working computation of paddings around labels etc.
97 97 // Expected to be replaced once we are done with the form refactoring.
98 98 @input-padding-px: 12px;
99 99 @legend-width: 220px;
100 100 @form-vertical-margin: 20px;
101 101 @form-check-width: 20px;
102 102 @form-radio-width: 10px;
103 103 @form-textcolor: @grey3;
104 104
105 105 // FORMS
106 106 @label-width: 220px;
107 107 //TODO: lisa: Eventually we don't need both of these; remove
108 108 // label-width when legend-width is no longer used
109 109
110 110 @input-border-thickness: @border-thickness;
111 111 @medium-inline-input-width: 115px;
112 112 @input-description-minwidth: 300px;
113 113 @label2-width: 200px;
114 114 @checkboxes-width: 420px;
115 115 @label-summary-minwidth: 80px;
116 116 @search-form-width: 400px;
117 117 @fields-input-m: 400px;
118 118 @fields-input-l: 800px;
119 119
120 120 // BUTTONS
121 121 @button-padding: .9em;
122 122
123 123 // DEFAULT WIDTHS
124 124 @wrapper-maxwidth: 1200px;
125 125 @sidebar-width: 145px;
126 126 @sidebar-all-width: @sidebar-width + 2 * @sidebarpadding;
127 127 @sidebar-small-width: 100px;
128 128 @sidebar-small-all-width: @sidebar-small-width + 2 * @sidebarpadding;
129 129 @texteditor-width: 660px;
130 130 @maincontent-maxwidth: 940px;
131 131 @pullrequest-width: 1025px;
132 132 @summary-menu-stats-width: 200px;
133 133
134 134 // SCREEN WIDTHS
135 135 @screen-sm-min: 320px;
136 136
137 137 // For Bootstrap
138 138 @panel-border-radius: @border-radius;
@@ -1,152 +1,152 b''
1 1 ## small box that displays changed/added/removed details fetched by AJAX
2 2 <%namespace name="base" file="/base/base.mako"/>
3 3
4 4
5 5 % if c.prev_page:
6 6 <tr>
7 7 <td colspan="9" class="load-more-commits">
8 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 9 ${_('load previous')}
10 10 </a>
11 11 </td>
12 12 </tr>
13 13 % endif
14 14
15 15 ## to speed up lookups cache some functions before the loop
16 16 <%
17 17 active_patterns = h.get_active_pattern_entries(c.repo_name)
18 18 urlify_commit_message = h.partial(h.urlify_commit_message, active_pattern_entries=active_patterns)
19 19 %>
20 20
21 21 % for cnt,commit in enumerate(c.pagination):
22 22 <tr id="sha_${commit.raw_id}" class="changelogRow container ${'tablerow%s' % (cnt%2)}">
23 23
24 24 <td class="td-checkbox">
25 25 ${h.checkbox(commit.raw_id,class_="commit-range")}
26 26 </td>
27 27 <td class="td-status">
28 28
29 29 %if c.statuses.get(commit.raw_id):
30 30 <div class="changeset-status-ico">
31 31 %if c.statuses.get(commit.raw_id)[2]:
32 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 33 <div class="${'flag_status {}'.format(c.statuses.get(commit.raw_id)[0])}"></div>
34 34 </a>
35 35 %else:
36 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 37 <div class="${'flag_status {}'.format(c.statuses.get(commit.raw_id)[0])}"></div>
38 38 </a>
39 39 %endif
40 40 </div>
41 41 %else:
42 42 <div class="tooltip flag_status not_reviewed" title="${_('Commit status: Not Reviewed')}"></div>
43 43 %endif
44 44 </td>
45 45 <td class="td-comments comments-col">
46 46 %if c.comments.get(commit.raw_id):
47 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 48 <i class="icon-comment"></i> ${len(c.comments[commit.raw_id])}
49 49 </a>
50 50 %endif
51 51 </td>
52 52 <td class="td-hash">
53 53 <code>
54 54
55 55 <a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id)}">
56 56 <span class="${'commit_hash obsolete' if getattr(commit, 'obsolete', None) else 'commit_hash'}">${h.show_id(commit)}</span>
57 57 </a>
58 58 <i class="tooltip icon-clipboard clipboard-action" data-clipboard-text="${commit.raw_id}" title="${_('Copy the full commit id')}"></i>
59 59 </code>
60 60 </td>
61 61 <td class="td-tags tags-col">
62 62 ## phase
63 63 % if hasattr(commit, 'phase'):
64 64 % if commit.phase != 'public':
65 65 <span class="tag phase-${commit.phase} tooltip" title="${_('Commit phase')}">${commit.phase}</span>
66 66 % endif
67 67 % endif
68 68
69 69 ## obsolete commits
70 70 % if hasattr(commit, 'obsolete'):
71 71 % if commit.obsolete:
72 72 <span class="tag obsolete-${commit.obsolete} tooltip" title="${_('Evolve State')}">${_('obsolete')}</span>
73 73 % endif
74 74 % endif
75 75
76 76 ## hidden commits
77 77 % if hasattr(commit, 'hidden'):
78 78 % if commit.hidden:
79 79 <span class="tag obsolete-${commit.hidden} tooltip" title="${_('Evolve State')}">${_('hidden')}</span>
80 80 % endif
81 81 % endif
82 82 </td>
83 83 <td class="td-message expand_commit" data-commit-id="${commit.raw_id}" title="${_('Expand commit message')}" onclick="commitsController.expandCommit(this); return false">
84 84 <div class="show_more_col">
85 <i class="show_more"></i>&nbsp;
85 <i class="icon-more-linked"></i>&nbsp;
86 86 </div>
87 87 </td>
88 88 <td class="td-description mid">
89 89 <div class="log-container truncate-wrap">
90 90 <div class="message truncate" id="c-${commit.raw_id}">${urlify_commit_message(commit.message, c.repo_name)}</div>
91 91 </div>
92 92 </td>
93 93
94 94 <td class="td-time">
95 95 ${h.age_component(commit.date)}
96 96 </td>
97 97 <td class="td-user">
98 98 ${base.gravatar_with_user(commit.author)}
99 99 </td>
100 100
101 101 <td class="td-tags tags-col">
102 102 <div id="t-${commit.raw_id}">
103 103
104 104 ## merge
105 105 %if commit.merge:
106 106 <span class="tag mergetag">
107 107 <i class="icon-merge"></i>${_('merge')}
108 108 </span>
109 109 %endif
110 110
111 111 ## branch
112 112 %if commit.branch:
113 113 <span class="tag branchtag" title="${h.tooltip(_('Branch %s') % commit.branch)}">
114 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 115 </span>
116 116 %endif
117 117
118 118 ## bookmarks
119 119 %if h.is_hg(c.rhodecode_repo):
120 120 %for book in commit.bookmarks:
121 121 <span class="tag booktag" title="${h.tooltip(_('Bookmark %s') % book)}">
122 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 123 </span>
124 124 %endfor
125 125 %endif
126 126
127 127 ## tags
128 128 %for tag in commit.tags:
129 129 <span class="tag tagtag" title="${h.tooltip(_('Tag %s') % tag)}">
130 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 131 </span>
132 132 %endfor
133 133
134 134 </div>
135 135 </td>
136 136 </tr>
137 137 % endfor
138 138
139 139 % if c.next_page:
140 140 <tr>
141 141 <td colspan="10" class="load-more-commits">
142 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 143 ${_('load next')}
144 144 </a>
145 145 </td>
146 146 </tr>
147 147 % endif
148 148 <tr class="chunk-graph-data" style="display:none"
149 149 data-graph='${c.graph_data|n}'
150 150 data-node='${c.prev_page}:${c.next_page}'
151 151 data-commits='${c.graph_commits|n}'>
152 152 </tr> No newline at end of file
@@ -1,117 +1,117 b''
1 1 ## Changesets table !
2 2 <%namespace name="base" file="/base/base.mako"/>
3 3
4 4 %if c.ancestor:
5 5 <div class="ancestor">${_('Common Ancestor Commit')}:
6 6 <a href="${h.route_path('repo_commit', repo_name=c.repo_name, commit_id=c.ancestor)}">
7 7 ${h.short_id(c.ancestor)}
8 8 </a>. ${_('Compare was calculated based on this shared commit.')}
9 9 <input id="common_ancestor" type="hidden" name="common_ancestor" value="${c.ancestor}">
10 10 </div>
11 11 %endif
12 12
13 13 <div class="container">
14 14 <input type="hidden" name="__start__" value="revisions:sequence">
15 15 <table class="rctable compare_view_commits">
16 16 <tr>
17 17 <th>${_('Time')}</th>
18 18 <th>${_('Author')}</th>
19 19 <th>${_('Commit')}</th>
20 20 <th></th>
21 21 <th>${_('Description')}</th>
22 22 </tr>
23 23 ## to speed up lookups cache some functions before the loop
24 24 <%
25 25 active_patterns = h.get_active_pattern_entries(c.repo_name)
26 26 urlify_commit_message = h.partial(h.urlify_commit_message, active_pattern_entries=active_patterns)
27 27 %>
28 28 %for commit in c.commit_ranges:
29 29 <tr id="row-${commit.raw_id}"
30 30 commit_id="${commit.raw_id}"
31 31 class="compare_select"
32 32 style="${'display: none' if c.collapse_all_commits else ''}"
33 33 >
34 34 <td class="td-time">
35 35 ${h.age_component(commit.date)}
36 36 </td>
37 37 <td class="td-user">
38 38 ${base.gravatar_with_user(commit.author, 16)}
39 39 </td>
40 40 <td class="td-hash">
41 41 <code>
42 42 <a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=commit.raw_id)}">
43 43 r${commit.idx}:${h.short_id(commit.raw_id)}
44 44 </a>
45 45 ${h.hidden('revisions',commit.raw_id)}
46 46 </code>
47 47 </td>
48 48 <td class="expand_commit"
49 49 data-commit-id="${commit.raw_id}"
50 50 title="${_( 'Expand commit message')}"
51 51 >
52 52 <div class="show_more_col">
53 <i class="show_more"></i>
53 <i class="icon-more-linked"></i>
54 54 </div>
55 55 </td>
56 56 <td class="mid td-description">
57 57 <div class="log-container truncate-wrap">
58 58 <div
59 59 id="c-${commit.raw_id}"
60 60 class="message truncate"
61 61 data-message-raw="${commit.message}"
62 62 >
63 63 ${urlify_commit_message(commit.message, c.repo_name)}
64 64 </div>
65 65 </div>
66 66 </td>
67 67 </tr>
68 68 %endfor
69 69 <tr class="compare_select_hidden" style="${'' if c.collapse_all_commits else 'display: none'}">
70 70 <td colspan="5">
71 71 ${_ungettext('%s commit hidden','%s commits hidden', len(c.commit_ranges)) % len(c.commit_ranges)},
72 72 <a href="#" onclick="$('.compare_select').show();$('.compare_select_hidden').hide(); return false">${_ungettext('show it','show them', len(c.commit_ranges))}</a>
73 73 </td>
74 74 </tr>
75 75 % if not c.commit_ranges:
76 76 <tr class="compare_select">
77 77 <td colspan="5">
78 78 ${_('No commits in this compare')}
79 79 </td>
80 80 </tr>
81 81 % endif
82 82 </table>
83 83 <input type="hidden" name="__end__" value="revisions:sequence">
84 84
85 85 </div>
86 86
87 87 <script>
88 88 $('.expand_commit').on('click',function(e){
89 89 var target_expand = $(this);
90 90 var cid = target_expand.data('commitId');
91 91
92 92 // ## TODO: dan: extract styles into css, and just toggleClass('open') here
93 93 if (target_expand.hasClass('open')){
94 94 $('#c-'+cid).css({
95 95 'height': '1.5em',
96 96 'white-space': 'nowrap',
97 97 'text-overflow': 'ellipsis',
98 98 'overflow':'hidden'
99 99 });
100 100 target_expand.removeClass('open');
101 101 }
102 102 else {
103 103 $('#c-'+cid).css({
104 104 'height': 'auto',
105 105 'white-space': 'pre-line',
106 106 'text-overflow': 'initial',
107 107 'overflow':'visible'
108 108 });
109 109 target_expand.addClass('open');
110 110 }
111 111 });
112 112
113 113 $('.compare_select').on('click',function(e){
114 114 var cid = $(this).attr('commit_id');
115 115 $('#row-'+cid).toggleClass('hl', !$('#row-'+cid).hasClass('hl'));
116 116 });
117 117 </script>
@@ -1,874 +1,874 b''
1 1 <%inherit file="/base/base.mako"/>
2 2 <%namespace name="base" file="/base/base.mako"/>
3 3 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
4 4
5 5 <%def name="title()">
6 6 ${_('%s Pull Request #%s') % (c.repo_name, c.pull_request.pull_request_id)}
7 7 %if c.rhodecode_name:
8 8 &middot; ${h.branding(c.rhodecode_name)}
9 9 %endif
10 10 </%def>
11 11
12 12 <%def name="breadcrumbs_links()">
13 13 <span id="pr-title">
14 14 ${c.pull_request.title}
15 15 %if c.pull_request.is_closed():
16 16 (${_('Closed')})
17 17 %endif
18 18 </span>
19 19 <div id="pr-title-edit" class="input" style="display: none;">
20 20 ${h.text('pullrequest_title', id_="pr-title-input", class_="large", value=c.pull_request.title)}
21 21 </div>
22 22 </%def>
23 23
24 24 <%def name="menu_bar_nav()">
25 25 ${self.menu_items(active='repositories')}
26 26 </%def>
27 27
28 28 <%def name="menu_bar_subnav()">
29 29 ${self.repo_menu(active='showpullrequest')}
30 30 </%def>
31 31
32 32 <%def name="main()">
33 33
34 34 <script type="text/javascript">
35 35 // TODO: marcink switch this to pyroutes
36 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 37 templateContext.pull_request_data.pull_request_id = ${c.pull_request.pull_request_id};
38 38 </script>
39 39 <div class="box">
40 40
41 41 <div class="title">
42 42 ${self.repo_page_title(c.rhodecode_db_repo)}
43 43 </div>
44 44
45 45 ${self.breadcrumbs()}
46 46
47 47 <div class="box pr-summary">
48 48
49 49 <div class="summary-details block-left">
50 50 <% summary = lambda n:{False:'summary-short'}.get(n) %>
51 51 <div class="pr-details-title">
52 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 53 %if c.allowed_to_update:
54 54 <div id="delete_pullrequest" class="pull-right action_button ${'' if c.allowed_to_delete else 'disabled' }" style="clear:inherit;padding: 0">
55 55 % if c.allowed_to_delete:
56 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 57 ${h.submit('remove_%s' % c.pull_request.pull_request_id, _('Delete'),
58 58 class_="btn btn-link btn-danger no-margin",onclick="return confirm('"+_('Confirm to delete this pull request')+"');")}
59 59 ${h.end_form()}
60 60 % else:
61 61 ${_('Delete')}
62 62 % endif
63 63 </div>
64 64 <div id="open_edit_pullrequest" class="pull-right action_button">${_('Edit')}</div>
65 65 <div id="close_edit_pullrequest" class="pull-right action_button" style="display: none;padding: 0">${_('Cancel')}</div>
66 66 %endif
67 67 </div>
68 68
69 69 <div id="summary" class="fields pr-details-content">
70 70 <div class="field">
71 71 <div class="label-summary">
72 72 <label>${_('Source')}:</label>
73 73 </div>
74 74 <div class="input">
75 75 <div class="pr-origininfo">
76 76 ## branch link is only valid if it is a branch
77 77 <span class="tag">
78 78 %if c.pull_request.source_ref_parts.type == 'branch':
79 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 80 %else:
81 81 ${c.pull_request.source_ref_parts.type}: ${c.pull_request.source_ref_parts.name}
82 82 %endif
83 83 </span>
84 84 <span class="clone-url">
85 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 86 </span>
87 87 <br/>
88 88 % if c.ancestor_commit:
89 89 ${_('Common ancestor')}:
90 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 91 % endif
92 92 </div>
93 93 %if h.is_hg(c.pull_request.source_repo):
94 94 <% clone_url = 'hg pull -r {} {}'.format(h.short_id(c.source_ref), c.pull_request.source_repo.clone_url()) %>
95 95 %elif h.is_git(c.pull_request.source_repo):
96 96 <% clone_url = 'git pull {} {}'.format(c.pull_request.source_repo.clone_url(), c.pull_request.source_ref_parts.name) %>
97 97 %endif
98 98
99 99 <div class="">
100 100 <input type="text" class="input-monospace pr-pullinfo" value="${clone_url}" readonly="readonly">
101 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 102 </div>
103 103
104 104 </div>
105 105 </div>
106 106 <div class="field">
107 107 <div class="label-summary">
108 108 <label>${_('Target')}:</label>
109 109 </div>
110 110 <div class="input">
111 111 <div class="pr-targetinfo">
112 112 ## branch link is only valid if it is a branch
113 113 <span class="tag">
114 114 %if c.pull_request.target_ref_parts.type == 'branch':
115 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 116 %else:
117 117 ${c.pull_request.target_ref_parts.type}: ${c.pull_request.target_ref_parts.name}
118 118 %endif
119 119 </span>
120 120 <span class="clone-url">
121 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 122 </span>
123 123 </div>
124 124 </div>
125 125 </div>
126 126
127 127 ## Link to the shadow repository.
128 128 <div class="field">
129 129 <div class="label-summary">
130 130 <label>${_('Merge')}:</label>
131 131 </div>
132 132 <div class="input">
133 133 % if not c.pull_request.is_closed() and c.pull_request.shadow_merge_ref:
134 134 %if h.is_hg(c.pull_request.target_repo):
135 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 136 %elif h.is_git(c.pull_request.target_repo):
137 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 138 %endif
139 139 <div class="">
140 140 <input type="text" class="input-monospace pr-mergeinfo" value="${clone_url}" readonly="readonly">
141 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 142 </div>
143 143 % else:
144 144 <div class="">
145 145 ${_('Shadow repository data not available')}.
146 146 </div>
147 147 % endif
148 148 </div>
149 149 </div>
150 150
151 151 <div class="field">
152 152 <div class="label-summary">
153 153 <label>${_('Review')}:</label>
154 154 </div>
155 155 <div class="input">
156 156 %if c.pull_request_review_status:
157 157 <div class="${'flag_status %s' % c.pull_request_review_status} tooltip pull-left"></div>
158 158 <span class="changeset-status-lbl tooltip">
159 159 %if c.pull_request.is_closed():
160 160 ${_('Closed')},
161 161 %endif
162 162 ${h.commit_status_lbl(c.pull_request_review_status)}
163 163 </span>
164 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 165 %endif
166 166 </div>
167 167 </div>
168 168 <div class="field">
169 169 <div class="pr-description-label label-summary" title="${_('Rendered using {} renderer').format(c.renderer)}">
170 170 <label>${_('Description')}:</label>
171 171 </div>
172 172 <div id="pr-desc" class="input">
173 173 <div class="pr-description">${h.render(c.pull_request.description, renderer=c.renderer)}</div>
174 174 </div>
175 175 <div id="pr-desc-edit" class="input textarea editor" style="display: none;">
176 176 <input id="pr-renderer-input" type="hidden" name="description_renderer" value="${c.visual.default_renderer}">
177 177 ${dt.markup_form('pr-description-input', form_text=c.pull_request.description)}
178 178 </div>
179 179 </div>
180 180
181 181 <div class="field">
182 182 <div class="label-summary">
183 183 <label>${_('Versions')}:</label>
184 184 </div>
185 185
186 186 <% outdated_comm_count_ver = len(c.inline_versions[None]['outdated']) %>
187 187 <% general_outdated_comm_count_ver = len(c.comment_versions[None]['outdated']) %>
188 188
189 189 <div class="pr-versions">
190 190 % if c.show_version_changes:
191 191 <% outdated_comm_count_ver = len(c.inline_versions[c.at_version_num]['outdated']) %>
192 192 <% general_outdated_comm_count_ver = len(c.comment_versions[c.at_version_num]['outdated']) %>
193 193 <a id="show-pr-versions" class="input" onclick="return versionController.toggleVersionView(this)" href="#show-pr-versions"
194 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 195 data-toggle-off="${_('Hide all versions of this pull request')}">
196 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 197 </a>
198 198 <table>
199 199 ## SHOW ALL VERSIONS OF PR
200 200 <% ver_pr = None %>
201 201
202 202 % for data in reversed(list(enumerate(c.versions, 1))):
203 203 <% ver_pos = data[0] %>
204 204 <% ver = data[1] %>
205 205 <% ver_pr = ver.pull_request_version_id %>
206 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 208 <tr class="version-pr" style="display: ${display_row}">
209 209 <td>
210 210 <code>
211 211 <a href="${request.current_route_path(_query=dict(version=ver_pr or 'latest'))}">v${ver_pos}</a>
212 212 </code>
213 213 </td>
214 214 <td>
215 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 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 217 </td>
218 218 <td>
219 219 <% review_status = c.review_versions[ver_pr].status if ver_pr in c.review_versions else 'not_reviewed' %>
220 220 <div class="${'flag_status %s' % review_status} tooltip pull-left" title="${_('Your review status at this version')}">
221 221 </div>
222 222 </td>
223 223 <td>
224 224 % if c.at_version_num != ver_pr:
225 225 <i class="icon-comment"></i>
226 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 227 G:${len(c.comment_versions[ver_pr]['at'])} / I:${len(c.inline_versions[ver_pr]['at'])}
228 228 </code>
229 229 % endif
230 230 </td>
231 231 <td>
232 232 ##<code>${ver.source_ref_parts.commit_id[:6]}</code>
233 233 </td>
234 234 <td>
235 235 ${h.age_component(ver.updated_on, time_is_local=True)}
236 236 </td>
237 237 </tr>
238 238 % endfor
239 239
240 240 <tr>
241 241 <td colspan="6">
242 242 <button id="show-version-diff" onclick="return versionController.showVersionDiff()" class="btn btn-sm" style="display: none"
243 243 data-label-text-locked="${_('select versions to show changes')}"
244 244 data-label-text-diff="${_('show changes between versions')}"
245 245 data-label-text-show="${_('show pull request for this version')}"
246 246 >
247 247 ${_('select versions to show changes')}
248 248 </button>
249 249 </td>
250 250 </tr>
251 251
252 252 ## show comment/inline comments summary
253 253 <%def name="comments_summary()">
254 254 <tr>
255 255 <td colspan="6" class="comments-summary-td">
256 256
257 257 % if c.at_version:
258 258 <% inline_comm_count_ver = len(c.inline_versions[c.at_version_num]['display']) %>
259 259 <% general_comm_count_ver = len(c.comment_versions[c.at_version_num]['display']) %>
260 260 ${_('Comments at this version')}:
261 261 % else:
262 262 <% inline_comm_count_ver = len(c.inline_versions[c.at_version_num]['until']) %>
263 263 <% general_comm_count_ver = len(c.comment_versions[c.at_version_num]['until']) %>
264 264 ${_('Comments for this pull request')}:
265 265 % endif
266 266
267 267
268 268 %if general_comm_count_ver:
269 269 <a href="#comments">${_("%d General ") % general_comm_count_ver}</a>
270 270 %else:
271 271 ${_("%d General ") % general_comm_count_ver}
272 272 %endif
273 273
274 274 %if inline_comm_count_ver:
275 275 , <a href="#" onclick="return Rhodecode.comments.nextComment();" id="inline-comments-counter">${_("%d Inline") % inline_comm_count_ver}</a>
276 276 %else:
277 277 , ${_("%d Inline") % inline_comm_count_ver}
278 278 %endif
279 279
280 280 %if outdated_comm_count_ver:
281 281 , <a href="#" onclick="showOutdated(); Rhodecode.comments.nextOutdatedComment(); return false;">${_("%d Outdated") % outdated_comm_count_ver}</a>
282 282 <a href="#" class="showOutdatedComments" onclick="showOutdated(this); return false;"> | ${_('show outdated comments')}</a>
283 283 <a href="#" class="hideOutdatedComments" style="display: none" onclick="hideOutdated(this); return false;"> | ${_('hide outdated comments')}</a>
284 284 %else:
285 285 , ${_("%d Outdated") % outdated_comm_count_ver}
286 286 %endif
287 287 </td>
288 288 </tr>
289 289 </%def>
290 290 ${comments_summary()}
291 291 </table>
292 292 % else:
293 293 <div class="input">
294 294 ${_('Pull request versions not available')}.
295 295 </div>
296 296 <div>
297 297 <table>
298 298 ${comments_summary()}
299 299 </table>
300 300 </div>
301 301 % endif
302 302 </div>
303 303 </div>
304 304
305 305 <div id="pr-save" class="field" style="display: none;">
306 306 <div class="label-summary"></div>
307 307 <div class="input">
308 308 <span id="edit_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</span>
309 309 </div>
310 310 </div>
311 311 </div>
312 312 </div>
313 313 <div>
314 314 ## AUTHOR
315 315 <div class="reviewers-title block-right">
316 316 <div class="pr-details-title">
317 317 ${_('Author of this pull request')}
318 318 </div>
319 319 </div>
320 320 <div class="block-right pr-details-content reviewers">
321 321 <ul class="group_members">
322 322 <li>
323 323 ${self.gravatar_with_user(c.pull_request.author.email, 16)}
324 324 </li>
325 325 </ul>
326 326 </div>
327 327
328 328 ## REVIEW RULES
329 329 <div id="review_rules" style="display: none" class="reviewers-title block-right">
330 330 <div class="pr-details-title">
331 331 ${_('Reviewer rules')}
332 332 %if c.allowed_to_update:
333 333 <span id="close_edit_reviewers" class="block-right action_button last-item" style="display: none;">${_('Close')}</span>
334 334 %endif
335 335 </div>
336 336 <div class="pr-reviewer-rules">
337 337 ## review rules will be appended here, by default reviewers logic
338 338 </div>
339 339 <input id="review_data" type="hidden" name="review_data" value="">
340 340 </div>
341 341
342 342 ## REVIEWERS
343 343 <div class="reviewers-title block-right">
344 344 <div class="pr-details-title">
345 345 ${_('Pull request reviewers')}
346 346 %if c.allowed_to_update:
347 347 <span id="open_edit_reviewers" class="block-right action_button last-item">${_('Edit')}</span>
348 348 %endif
349 349 </div>
350 350 </div>
351 351 <div id="reviewers" class="block-right pr-details-content reviewers">
352 352
353 353 ## members redering block
354 354 <input type="hidden" name="__start__" value="review_members:sequence">
355 355 <ul id="review_members" class="group_members">
356 356
357 357 % for review_obj, member, reasons, mandatory, status in c.pull_request_reviewers:
358 358 <script>
359 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 360 var status = "${(status[0][1].status if status else 'not_reviewed')}";
361 361 var status_lbl = "${h.commit_status_lbl(status[0][1].status if status else 'not_reviewed')}";
362 362 var allowed_to_update = ${h.json.dumps(c.allowed_to_update)};
363 363
364 364 var entry = renderTemplate('reviewMemberEntry', {
365 365 'member': member,
366 366 'mandatory': member.mandatory,
367 367 'reasons': member.reasons,
368 368 'allowed_to_update': allowed_to_update,
369 369 'review_status': status,
370 370 'review_status_label': status_lbl,
371 371 'user_group': member.user_group,
372 372 'create': false
373 373 });
374 374 $('#review_members').append(entry)
375 375 </script>
376 376
377 377 % endfor
378 378
379 379 </ul>
380 380 <input type="hidden" name="__end__" value="review_members:sequence">
381 381 ## end members redering block
382 382
383 383 %if not c.pull_request.is_closed():
384 384 <div id="add_reviewer" class="ac" style="display: none;">
385 385 %if c.allowed_to_update:
386 386 % if not c.forbid_adding_reviewers:
387 387 <div id="add_reviewer_input" class="reviewer_ac">
388 388 ${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))}
389 389 <div id="reviewers_container"></div>
390 390 </div>
391 391 % endif
392 392 <div class="pull-right">
393 393 <button id="update_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</button>
394 394 </div>
395 395 %endif
396 396 </div>
397 397 %endif
398 398 </div>
399 399 </div>
400 400 </div>
401 401 <div class="box">
402 402 ##DIFF
403 403 <div class="table" >
404 404 <div id="changeset_compare_view_content">
405 405 ##CS
406 406 % if c.missing_requirements:
407 407 <div class="box">
408 408 <div class="alert alert-warning">
409 409 <div>
410 410 <strong>${_('Missing requirements:')}</strong>
411 411 ${_('These commits cannot be displayed, because this repository uses the Mercurial largefiles extension, which was not enabled.')}
412 412 </div>
413 413 </div>
414 414 </div>
415 415 % elif c.missing_commits:
416 416 <div class="box">
417 417 <div class="alert alert-warning">
418 418 <div>
419 419 <strong>${_('Missing commits')}:</strong>
420 420 ${_('This pull request cannot be displayed, because one or more commits no longer exist in the source repository.')}
421 421 ${_('Please update this pull request, push the commits back into the source repository, or consider closing this pull request.')}
422 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 423 </div>
424 424 </div>
425 425 </div>
426 426 % endif
427 427
428 428 <div class="compare_view_commits_title">
429 429 % if not c.compare_mode:
430 430
431 431 % if c.at_version_pos:
432 432 <h4>
433 433 ${_('Showing changes at v%d, commenting is disabled.') % c.at_version_pos}
434 434 </h4>
435 435 % endif
436 436
437 437 <div class="pull-left">
438 438 <div class="btn-group">
439 439 <a
440 440 class="btn"
441 441 href="#"
442 442 onclick="$('.compare_select').show();$('.compare_select_hidden').hide(); return false">
443 443 ${_ungettext('Expand %s commit','Expand %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
444 444 </a>
445 445 <a
446 446 class="btn"
447 447 href="#"
448 448 onclick="$('.compare_select').hide();$('.compare_select_hidden').show(); return false">
449 449 ${_ungettext('Collapse %s commit','Collapse %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
450 450 </a>
451 451 </div>
452 452 </div>
453 453
454 454 <div class="pull-right">
455 455 % if c.allowed_to_update and not c.pull_request.is_closed():
456 456 <a id="update_commits" class="btn btn-primary no-margin pull-right">${_('Update commits')}</a>
457 457 % else:
458 458 <a class="tooltip btn disabled pull-right" disabled="disabled" title="${_('Update is disabled for current view')}">${_('Update commits')}</a>
459 459 % endif
460 460
461 461 </div>
462 462 % endif
463 463 </div>
464 464
465 465 % if not c.missing_commits:
466 466 % if c.compare_mode:
467 467 % if c.at_version:
468 468 <h4>
469 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 470 </h4>
471 471
472 472 <div class="subtitle-compare">
473 473 ${_('commits added: {}, removed: {}').format(len(c.commit_changes_summary.added), len(c.commit_changes_summary.removed))}
474 474 </div>
475 475
476 476 <div class="container">
477 477 <table class="rctable compare_view_commits">
478 478 <tr>
479 479 <th></th>
480 480 <th>${_('Time')}</th>
481 481 <th>${_('Author')}</th>
482 482 <th>${_('Commit')}</th>
483 483 <th></th>
484 484 <th>${_('Description')}</th>
485 485 </tr>
486 486
487 487 % for c_type, commit in c.commit_changes:
488 488 % if c_type in ['a', 'r']:
489 489 <%
490 490 if c_type == 'a':
491 491 cc_title = _('Commit added in displayed changes')
492 492 elif c_type == 'r':
493 493 cc_title = _('Commit removed in displayed changes')
494 494 else:
495 495 cc_title = ''
496 496 %>
497 497 <tr id="row-${commit.raw_id}" commit_id="${commit.raw_id}" class="compare_select">
498 498 <td>
499 499 <div class="commit-change-indicator color-${c_type}-border">
500 500 <div class="commit-change-content color-${c_type} tooltip" title="${h.tooltip(cc_title)}">
501 501 ${c_type.upper()}
502 502 </div>
503 503 </div>
504 504 </td>
505 505 <td class="td-time">
506 506 ${h.age_component(commit.date)}
507 507 </td>
508 508 <td class="td-user">
509 509 ${base.gravatar_with_user(commit.author, 16)}
510 510 </td>
511 511 <td class="td-hash">
512 512 <code>
513 513 <a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=commit.raw_id)}">
514 514 r${commit.idx}:${h.short_id(commit.raw_id)}
515 515 </a>
516 516 ${h.hidden('revisions', commit.raw_id)}
517 517 </code>
518 518 </td>
519 519 <td class="expand_commit" data-commit-id="${commit.raw_id}" title="${_( 'Expand commit message')}">
520 520 <div class="show_more_col">
521 <i class="show_more"></i>
521 <i class="icon-more-linked"></i>
522 522 </div>
523 523 </td>
524 524 <td class="mid td-description">
525 525 <div class="log-container truncate-wrap">
526 526 <div class="message truncate" id="c-${commit.raw_id}" data-message-raw="${commit.message}">
527 527 ${h.urlify_commit_message(commit.message, c.repo_name)}
528 528 </div>
529 529 </div>
530 530 </td>
531 531 </tr>
532 532 % endif
533 533 % endfor
534 534 </table>
535 535 </div>
536 536
537 537 <script>
538 538 $('.expand_commit').on('click',function(e){
539 539 var target_expand = $(this);
540 540 var cid = target_expand.data('commitId');
541 541
542 542 if (target_expand.hasClass('open')){
543 543 $('#c-'+cid).css({
544 544 'height': '1.5em',
545 545 'white-space': 'nowrap',
546 546 'text-overflow': 'ellipsis',
547 547 'overflow':'hidden'
548 548 });
549 549 target_expand.removeClass('open');
550 550 }
551 551 else {
552 552 $('#c-'+cid).css({
553 553 'height': 'auto',
554 554 'white-space': 'pre-line',
555 555 'text-overflow': 'initial',
556 556 'overflow':'visible'
557 557 });
558 558 target_expand.addClass('open');
559 559 }
560 560 });
561 561 </script>
562 562
563 563 % endif
564 564
565 565 % else:
566 566 <%include file="/compare/compare_commits.mako" />
567 567 % endif
568 568
569 569 <div class="cs_files">
570 570 <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/>
571 571
572 572 ${cbdiffs.render_diffset_menu(c.diffset, range_diff_on=c.range_diff_on)}
573 573
574 574 % if c.range_diff_on:
575 575 % for commit in c.commit_ranges:
576 576 ${cbdiffs.render_diffset(
577 577 c.changes[commit.raw_id],
578 578 commit=commit, use_comments=True,
579 579 collapse_when_files_over=5,
580 580 disable_new_comments=True,
581 581 deleted_files_comments=c.deleted_files_comments,
582 582 inline_comments=c.inline_comments)}
583 583 % endfor
584 584 % else:
585 585 ${cbdiffs.render_diffset(
586 586 c.diffset, use_comments=True,
587 587 collapse_when_files_over=30,
588 588 disable_new_comments=not c.allowed_to_comment,
589 589 deleted_files_comments=c.deleted_files_comments,
590 590 inline_comments=c.inline_comments)}
591 591 % endif
592 592
593 593 </div>
594 594 % else:
595 595 ## skipping commits we need to clear the view for missing commits
596 596 <div style="clear:both;"></div>
597 597 % endif
598 598
599 599 </div>
600 600 </div>
601 601
602 602 ## template for inline comment form
603 603 <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
604 604
605 605 ## render general comments
606 606
607 607 <div id="comment-tr-show">
608 608 <div class="comment">
609 609 % if general_outdated_comm_count_ver:
610 610 <div class="meta">
611 611 % if general_outdated_comm_count_ver == 1:
612 612 ${_('there is {num} general comment from older versions').format(num=general_outdated_comm_count_ver)},
613 613 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show it')}</a>
614 614 % else:
615 615 ${_('there are {num} general comments from older versions').format(num=general_outdated_comm_count_ver)},
616 616 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show them')}</a>
617 617 % endif
618 618 </div>
619 619 % endif
620 620 </div>
621 621 </div>
622 622
623 623 ${comment.generate_comments(c.comments, include_pull_request=True, is_pull_request=True)}
624 624
625 625 % if not c.pull_request.is_closed():
626 626 ## merge status, and merge action
627 627 <div class="pull-request-merge">
628 628 <%include file="/pullrequests/pullrequest_merge_checks.mako"/>
629 629 </div>
630 630
631 631 ## main comment form and it status
632 632 ${comment.comments(h.route_path('pullrequest_comment_create', repo_name=c.repo_name,
633 633 pull_request_id=c.pull_request.pull_request_id),
634 634 c.pull_request_review_status,
635 635 is_pull_request=True, change_status=c.allowed_to_change_status)}
636 636 %endif
637 637
638 638 <script type="text/javascript">
639 639 if (location.hash) {
640 640 var result = splitDelimitedHash(location.hash);
641 641 var line = $('html').find(result.loc);
642 642 // show hidden comments if we use location.hash
643 643 if (line.hasClass('comment-general')) {
644 644 $(line).show();
645 645 } else if (line.hasClass('comment-inline')) {
646 646 $(line).show();
647 647 var $cb = $(line).closest('.cb');
648 648 $cb.removeClass('cb-collapsed')
649 649 }
650 650 if (line.length > 0){
651 651 offsetScroll(line, 70);
652 652 }
653 653 }
654 654
655 655 versionController = new VersionController();
656 656 versionController.init();
657 657
658 658 reviewersController = new ReviewersController();
659 659
660 660 $(function(){
661 661
662 662 // custom code mirror
663 663 var codeMirrorInstance = $('#pr-description-input').get(0).MarkupForm.cm;
664 664
665 665 var PRDetails = {
666 666 editButton: $('#open_edit_pullrequest'),
667 667 closeButton: $('#close_edit_pullrequest'),
668 668 deleteButton: $('#delete_pullrequest'),
669 669 viewFields: $('#pr-desc, #pr-title'),
670 670 editFields: $('#pr-desc-edit, #pr-title-edit, #pr-save'),
671 671
672 672 init: function() {
673 673 var that = this;
674 674 this.editButton.on('click', function(e) { that.edit(); });
675 675 this.closeButton.on('click', function(e) { that.view(); });
676 676 },
677 677
678 678 edit: function(event) {
679 679 this.viewFields.hide();
680 680 this.editButton.hide();
681 681 this.deleteButton.hide();
682 682 this.closeButton.show();
683 683 this.editFields.show();
684 684 codeMirrorInstance.refresh();
685 685 },
686 686
687 687 view: function(event) {
688 688 this.editButton.show();
689 689 this.deleteButton.show();
690 690 this.editFields.hide();
691 691 this.closeButton.hide();
692 692 this.viewFields.show();
693 693 }
694 694 };
695 695
696 696 var ReviewersPanel = {
697 697 editButton: $('#open_edit_reviewers'),
698 698 closeButton: $('#close_edit_reviewers'),
699 699 addButton: $('#add_reviewer'),
700 700 removeButtons: $('.reviewer_member_remove,.reviewer_member_mandatory_remove'),
701 701
702 702 init: function() {
703 703 var self = this;
704 704 this.editButton.on('click', function(e) { self.edit(); });
705 705 this.closeButton.on('click', function(e) { self.close(); });
706 706 },
707 707
708 708 edit: function(event) {
709 709 this.editButton.hide();
710 710 this.closeButton.show();
711 711 this.addButton.show();
712 712 this.removeButtons.css('visibility', 'visible');
713 713 // review rules
714 714 reviewersController.loadReviewRules(
715 715 ${c.pull_request.reviewer_data_json | n});
716 716 },
717 717
718 718 close: function(event) {
719 719 this.editButton.show();
720 720 this.closeButton.hide();
721 721 this.addButton.hide();
722 722 this.removeButtons.css('visibility', 'hidden');
723 723 // hide review rules
724 724 reviewersController.hideReviewRules()
725 725 }
726 726 };
727 727
728 728 PRDetails.init();
729 729 ReviewersPanel.init();
730 730
731 731 showOutdated = function(self){
732 732 $('.comment-inline.comment-outdated').show();
733 733 $('.filediff-outdated').show();
734 734 $('.showOutdatedComments').hide();
735 735 $('.hideOutdatedComments').show();
736 736 };
737 737
738 738 hideOutdated = function(self){
739 739 $('.comment-inline.comment-outdated').hide();
740 740 $('.filediff-outdated').hide();
741 741 $('.hideOutdatedComments').hide();
742 742 $('.showOutdatedComments').show();
743 743 };
744 744
745 745 refreshMergeChecks = function(){
746 746 var loadUrl = "${request.current_route_path(_query=dict(merge_checks=1))}";
747 747 $('.pull-request-merge').css('opacity', 0.3);
748 748 $('.action-buttons-extra').css('opacity', 0.3);
749 749
750 750 $('.pull-request-merge').load(
751 751 loadUrl, function() {
752 752 $('.pull-request-merge').css('opacity', 1);
753 753
754 754 $('.action-buttons-extra').css('opacity', 1);
755 755 injectCloseAction();
756 756 }
757 757 );
758 758 };
759 759
760 760 injectCloseAction = function() {
761 761 var closeAction = $('#close-pull-request-action').html();
762 762 var $actionButtons = $('.action-buttons-extra');
763 763 // clear the action before
764 764 $actionButtons.html("");
765 765 $actionButtons.html(closeAction);
766 766 };
767 767
768 768 closePullRequest = function (status) {
769 769 // inject closing flag
770 770 $('.action-buttons-extra').append('<input type="hidden" class="close-pr-input" id="close_pull_request" value="1">');
771 771 $(generalCommentForm.statusChange).select2("val", status).trigger('change');
772 772 $(generalCommentForm.submitForm).submit();
773 773 };
774 774
775 775 $('#show-outdated-comments').on('click', function(e){
776 776 var button = $(this);
777 777 var outdated = $('.comment-outdated');
778 778
779 779 if (button.html() === "(Show)") {
780 780 button.html("(Hide)");
781 781 outdated.show();
782 782 } else {
783 783 button.html("(Show)");
784 784 outdated.hide();
785 785 }
786 786 });
787 787
788 788 $('.show-inline-comments').on('change', function(e){
789 789 var show = 'none';
790 790 var target = e.currentTarget;
791 791 if(target.checked){
792 792 show = ''
793 793 }
794 794 var boxid = $(target).attr('id_for');
795 795 var comments = $('#{0} .inline-comments'.format(boxid));
796 796 var fn_display = function(idx){
797 797 $(this).css('display', show);
798 798 };
799 799 $(comments).each(fn_display);
800 800 var btns = $('#{0} .inline-comments-button'.format(boxid));
801 801 $(btns).each(fn_display);
802 802 });
803 803
804 804 $('#merge_pull_request_form').submit(function() {
805 805 if (!$('#merge_pull_request').attr('disabled')) {
806 806 $('#merge_pull_request').attr('disabled', 'disabled');
807 807 }
808 808 return true;
809 809 });
810 810
811 811 $('#edit_pull_request').on('click', function(e){
812 812 var title = $('#pr-title-input').val();
813 813 var description = codeMirrorInstance.getValue();
814 814 var renderer = $('#pr-renderer-input').val();
815 815 editPullRequest(
816 816 "${c.repo_name}", "${c.pull_request.pull_request_id}",
817 817 title, description, renderer);
818 818 });
819 819
820 820 $('#update_pull_request').on('click', function(e){
821 821 $(this).attr('disabled', 'disabled');
822 822 $(this).addClass('disabled');
823 823 $(this).html(_gettext('Saving...'));
824 824 reviewersController.updateReviewers(
825 825 "${c.repo_name}", "${c.pull_request.pull_request_id}");
826 826 });
827 827
828 828 $('#update_commits').on('click', function(e){
829 829 var isDisabled = !$(e.currentTarget).attr('disabled');
830 830 $(e.currentTarget).attr('disabled', 'disabled');
831 831 $(e.currentTarget).addClass('disabled');
832 832 $(e.currentTarget).removeClass('btn-primary');
833 833 $(e.currentTarget).text(_gettext('Updating...'));
834 834 if(isDisabled){
835 835 updateCommits(
836 836 "${c.repo_name}", "${c.pull_request.pull_request_id}");
837 837 }
838 838 });
839 839 // fixing issue with caches on firefox
840 840 $('#update_commits').removeAttr("disabled");
841 841
842 842 $('.show-inline-comments').on('click', function(e){
843 843 var boxid = $(this).attr('data-comment-id');
844 844 var button = $(this);
845 845
846 846 if(button.hasClass("comments-visible")) {
847 847 $('#{0} .inline-comments'.format(boxid)).each(function(index){
848 848 $(this).hide();
849 849 });
850 850 button.removeClass("comments-visible");
851 851 } else {
852 852 $('#{0} .inline-comments'.format(boxid)).each(function(index){
853 853 $(this).show();
854 854 });
855 855 button.addClass("comments-visible");
856 856 }
857 857 });
858 858
859 859 // register submit callback on commentForm form to track TODOs
860 860 window.commentFormGlobalSubmitSuccessCallback = function(){
861 861 refreshMergeChecks();
862 862 };
863 863 // initial injection
864 864 injectCloseAction();
865 865
866 866 ReviewerAutoComplete('#user');
867 867
868 868 })
869 869 </script>
870 870
871 871 </div>
872 872 </div>
873 873
874 874 </%def>
@@ -1,108 +1,107 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.mako"/>
3 3
4 4 <%def name="title()">
5 5 %if c.repo_name:
6 6 ${_('Search inside repository %(repo_name)s') % {'repo_name': c.repo_name}}
7 7 %else:
8 8 ${_('Search inside all accessible repositories')}
9 9 %endif
10 10 %if c.rhodecode_name:
11 11 &middot; ${h.branding(c.rhodecode_name)}
12 12 %endif
13 13 </%def>
14 14
15 15 <%def name="breadcrumbs_links()">
16 16 %if c.repo_name:
17 17 ${_('Search inside repository %(repo_name)s') % {'repo_name': c.repo_name}}
18 18 %else:
19 19 ${_('Search inside all accessible repositories')}
20 20 %endif
21 21 %if c.cur_query:
22 22 &raquo;
23 23 ${c.cur_query}
24 24 %endif
25 25 </%def>
26 26
27 27 <%def name="menu_bar_nav()">
28 28 %if c.repo_name:
29 29 ${self.menu_items(active='repositories')}
30 30 %else:
31 31 ${self.menu_items(active='search')}
32 32 %endif
33 33 </%def>
34 34
35 35 <%def name="menu_bar_subnav()">
36 36 %if c.repo_name:
37 37 ${self.repo_menu(active='options')}
38 38 %endif
39 39 </%def>
40 40
41 41 <%def name="main()">
42 42 <div class="box">
43 43 %if c.repo_name:
44 44 <!-- box / title -->
45 45 <div class="title">
46 46 ${self.repo_page_title(c.rhodecode_db_repo)}
47 47 </div>
48 48 ${h.form(h.route_path('search_repo',repo_name=c.repo_name),method='get')}
49 49 %else:
50 50 <!-- box / title -->
51 51 <div class="title">
52 52 ${self.breadcrumbs()}
53 53 <ul class="links">&nbsp;</ul>
54 54 </div>
55 55 <!-- end box / title -->
56 56 ${h.form(h.route_path('search'), method='get')}
57 57 %endif
58 58 <div class="form search-form">
59 59 <div class="fields">
60 <label for="q">${_('Search item')}:</label>
61 ${h.text('q', c.cur_query)}
60 ${h.text('q', c.cur_query, placeholder="Enter query...")}
62 61
63 62 ${h.select('type',c.search_type,[('content',_('File contents')), ('commit',_('Commit messages')), ('path',_('File names')),],id='id_search_type')}
64 63 <input type="submit" value="${_('Search')}" class="btn"/>
65 64 <br/>
66 65
67 66 <div class="search-feedback-items">
68 67 % for error in c.errors:
69 68 <span class="error-message">
70 69 % for k,v in error.asdict().items():
71 70 ${k} - ${v}
72 71 % endfor
73 72 </span>
74 73 % endfor
75 74 <div class="field">
76 75 <p class="filterexample" style="position: inherit" onclick="$('#search-help').toggle()">${_('Example Queries')}</p>
77 76 <pre id="search-help" style="display: none">${h.tooltip(h.search_filter_help(c.searcher, request))}</pre>
78 77 </div>
79 78
80 79 <div class="field">${c.runtime}</div>
81 80 </div>
82 81 </div>
83 82 </div>
84 83
85 84 ${h.end_form()}
86 85 <div class="search">
87 86 % if c.search_type == 'content':
88 87 <%include file='search_content.mako'/>
89 88 % elif c.search_type == 'path':
90 89 <%include file='search_path.mako'/>
91 90 % elif c.search_type == 'commit':
92 91 <%include file='search_commit.mako'/>
93 92 % elif c.search_type == 'repository':
94 93 <%include file='search_repository.mako'/>
95 94 % endif
96 95 </div>
97 96 </div>
98 97 <script>
99 98 $(document).ready(function(){
100 99 $("#id_search_type").select2({
101 100 'containerCssClass': "drop-menu",
102 101 'dropdownCssClass': "drop-menu-dropdown",
103 102 'dropdownAutoWidth': true,
104 103 'minimumResultsForSearch': -1
105 104 });
106 105 })
107 106 </script>
108 107 </%def>
@@ -1,82 +1,82 b''
1 1 <%namespace name="base" file="/base/base.mako"/>
2 2
3 3 <table class="rctable search-results">
4 4 <tr>
5 5 <th>${_('Repository')}</th>
6 6 <th>${_('Commit')}</th>
7 7 <th></th>
8 8 <th>${_('Commit message')}</th>
9 9 <th>
10 10 %if c.sort == 'newfirst':
11 11 <a href="${c.url_generator(sort='oldfirst')}">${_('Age (new first)')}</a>
12 12 %else:
13 13 <a href="${c.url_generator(sort='newfirst')}">${_('Age (old first)')}</a>
14 14 %endif
15 15 </th>
16 16 <th>${_('Author')}</th>
17 17 </tr>
18 18 %for entry in c.formatted_results:
19 19 ## search results are additionally filtered, and this check is just a safe gate
20 20 % if h.HasRepoPermissionAny('repository.write','repository.read','repository.admin')(entry['repository'], 'search results commit check'):
21 21 <tr class="body">
22 22 <td class="td-componentname">
23 23 %if h.get_repo_type_by_name(entry.get('repository')) == 'hg':
24 24 <i class="icon-hg"></i>
25 25 %elif h.get_repo_type_by_name(entry.get('repository')) == 'git':
26 26 <i class="icon-git"></i>
27 27 %elif h.get_repo_type_by_name(entry.get('repository')) == 'svn':
28 28 <i class="icon-svn"></i>
29 29 %endif
30 30 ${h.link_to(entry['repository'], h.route_path('repo_summary',repo_name=entry['repository']))}
31 31 </td>
32 32 <td class="td-commit">
33 33 ${h.link_to(h._shorten_commit_id(entry['commit_id']),
34 34 h.route_path('repo_commit',repo_name=entry['repository'],commit_id=entry['commit_id']))}
35 35 </td>
36 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 37 <div class="show_more_col">
38 <i class="show_more"></i>&nbsp;
38 <i class="icon-more-linked"></i>&nbsp;
39 39 </div>
40 40 </td>
41 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 42 %if entry.get('message_hl'):
43 43 ${h.literal(entry['message_hl'])}
44 44 %else:
45 45 ${h.urlify_commit_message(entry['message'], entry['repository'])}
46 46 %endif
47 47 </td>
48 48 <td class="td-time">
49 49 ${h.age_component(h.time_to_utcdatetime(entry['date']))}
50 50 </td>
51 51
52 52 <td class="td-user author">
53 53 ${base.gravatar_with_user(entry['author'])}
54 54 </td>
55 55 </tr>
56 56 % endif
57 57 %endfor
58 58 </table>
59 59
60 60 %if c.cur_query and c.formatted_results:
61 61 <div class="pagination-wh pagination-left">
62 62 ${c.formatted_results.pager('$link_previous ~2~ $link_next')}
63 63 </div>
64 64 %endif
65 65
66 66 <script>
67 67 $('.expand_commit').on('click',function(e){
68 68 var target_expand = $(this);
69 69 var cid = target_expand.data('commit-id');
70 70
71 71 if (target_expand.hasClass('open')){
72 72 $('#c-'+cid).css({'height': '1.5em', 'white-space': 'nowrap', 'text-overflow': 'ellipsis', 'overflow':'hidden'})
73 73 $('#t-'+cid).css({'height': 'auto', 'line-height': '.9em', 'text-overflow': 'ellipsis', 'overflow':'hidden'})
74 74 target_expand.removeClass('open');
75 75 }
76 76 else {
77 77 $('#c-'+cid).css({'height': 'auto', 'white-space': 'normal', 'text-overflow': 'initial', 'overflow':'visible'})
78 78 $('#t-'+cid).css({'height': 'auto', 'max-height': 'none', 'text-overflow': 'initial', 'overflow':'visible'})
79 79 target_expand.addClass('open');
80 80 }
81 81 });
82 82 </script>
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
General Comments 0
You need to be logged in to leave comments. Login now