##// END OF EJS Templates
template: use Bootstrap tooltips and popover instead of handmade tooltips...
domruf -
r6394:1ab38cd7 default
parent child Browse files
Show More
@@ -1,473 +1,473 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 # This program is free software: you can redistribute it and/or modify
2 # This program is free software: you can redistribute it and/or modify
3 # it under the terms of the GNU General Public License as published by
3 # it under the terms of the GNU General Public License as published by
4 # the Free Software Foundation, either version 3 of the License, or
4 # the Free Software Foundation, either version 3 of the License, or
5 # (at your option) any later version.
5 # (at your option) any later version.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU General Public License
12 # You should have received a copy of the GNU General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 """
14 """
15 kallithea.controllers.changeset
15 kallithea.controllers.changeset
16 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17
17
18 changeset controller showing changes between revisions
18 changeset controller showing changes between revisions
19
19
20 This file was forked by the Kallithea project in July 2014.
20 This file was forked by the Kallithea project in July 2014.
21 Original author and date, and relevant copyright and licensing information is below:
21 Original author and date, and relevant copyright and licensing information is below:
22 :created_on: Apr 25, 2010
22 :created_on: Apr 25, 2010
23 :author: marcink
23 :author: marcink
24 :copyright: (c) 2013 RhodeCode GmbH, and others.
24 :copyright: (c) 2013 RhodeCode GmbH, and others.
25 :license: GPLv3, see LICENSE.md for more details.
25 :license: GPLv3, see LICENSE.md for more details.
26 """
26 """
27
27
28 import logging
28 import logging
29 import traceback
29 import traceback
30 from collections import defaultdict
30 from collections import defaultdict
31
31
32 from pylons import tmpl_context as c, request, response
32 from pylons import tmpl_context as c, request, response
33 from pylons.i18n.translation import _
33 from pylons.i18n.translation import _
34 from webob.exc import HTTPFound, HTTPForbidden, HTTPBadRequest, HTTPNotFound
34 from webob.exc import HTTPFound, HTTPForbidden, HTTPBadRequest, HTTPNotFound
35
35
36 from kallithea.lib.utils import jsonify
36 from kallithea.lib.utils import jsonify
37 from kallithea.lib.vcs.exceptions import RepositoryError, \
37 from kallithea.lib.vcs.exceptions import RepositoryError, \
38 ChangesetDoesNotExistError, EmptyRepositoryError
38 ChangesetDoesNotExistError, EmptyRepositoryError
39
39
40 from kallithea.lib.compat import json
40 from kallithea.lib.compat import json
41 import kallithea.lib.helpers as h
41 import kallithea.lib.helpers as h
42 from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator, \
42 from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator, \
43 NotAnonymous
43 NotAnonymous
44 from kallithea.lib.base import BaseRepoController, render
44 from kallithea.lib.base import BaseRepoController, render
45 from kallithea.lib.utils import action_logger
45 from kallithea.lib.utils import action_logger
46 from kallithea.lib.compat import OrderedDict
46 from kallithea.lib.compat import OrderedDict
47 from kallithea.lib import diffs
47 from kallithea.lib import diffs
48 from kallithea.model.db import ChangesetComment, ChangesetStatus
48 from kallithea.model.db import ChangesetComment, ChangesetStatus
49 from kallithea.model.comment import ChangesetCommentsModel
49 from kallithea.model.comment import ChangesetCommentsModel
50 from kallithea.model.changeset_status import ChangesetStatusModel
50 from kallithea.model.changeset_status import ChangesetStatusModel
51 from kallithea.model.meta import Session
51 from kallithea.model.meta import Session
52 from kallithea.model.repo import RepoModel
52 from kallithea.model.repo import RepoModel
53 from kallithea.lib.diffs import LimitedDiffContainer
53 from kallithea.lib.diffs import LimitedDiffContainer
54 from kallithea.lib.exceptions import StatusChangeOnClosedPullRequestError
54 from kallithea.lib.exceptions import StatusChangeOnClosedPullRequestError
55 from kallithea.lib.vcs.backends.base import EmptyChangeset
55 from kallithea.lib.vcs.backends.base import EmptyChangeset
56 from kallithea.lib.utils2 import safe_unicode
56 from kallithea.lib.utils2 import safe_unicode
57 from kallithea.lib.graphmod import graph_data
57 from kallithea.lib.graphmod import graph_data
58
58
59 log = logging.getLogger(__name__)
59 log = logging.getLogger(__name__)
60
60
61
61
62 def _update_with_GET(params, GET):
62 def _update_with_GET(params, GET):
63 for k in ['diff1', 'diff2', 'diff']:
63 for k in ['diff1', 'diff2', 'diff']:
64 params[k] += GET.getall(k)
64 params[k] += GET.getall(k)
65
65
66
66
67 def anchor_url(revision, path, GET):
67 def anchor_url(revision, path, GET):
68 fid = h.FID(revision, path)
68 fid = h.FID(revision, path)
69 return h.url.current(anchor=fid, **dict(GET))
69 return h.url.current(anchor=fid, **dict(GET))
70
70
71
71
72 def get_ignore_ws(fid, GET):
72 def get_ignore_ws(fid, GET):
73 ig_ws_global = GET.get('ignorews')
73 ig_ws_global = GET.get('ignorews')
74 ig_ws = filter(lambda k: k.startswith('WS'), GET.getall(fid))
74 ig_ws = filter(lambda k: k.startswith('WS'), GET.getall(fid))
75 if ig_ws:
75 if ig_ws:
76 try:
76 try:
77 return int(ig_ws[0].split(':')[-1])
77 return int(ig_ws[0].split(':')[-1])
78 except ValueError:
78 except ValueError:
79 raise HTTPBadRequest()
79 raise HTTPBadRequest()
80 return ig_ws_global
80 return ig_ws_global
81
81
82
82
83 def _ignorews_url(GET, fileid=None):
83 def _ignorews_url(GET, fileid=None):
84 fileid = str(fileid) if fileid else None
84 fileid = str(fileid) if fileid else None
85 params = defaultdict(list)
85 params = defaultdict(list)
86 _update_with_GET(params, GET)
86 _update_with_GET(params, GET)
87 lbl = _('Show whitespace')
87 lbl = _('Show whitespace')
88 ig_ws = get_ignore_ws(fileid, GET)
88 ig_ws = get_ignore_ws(fileid, GET)
89 ln_ctx = get_line_ctx(fileid, GET)
89 ln_ctx = get_line_ctx(fileid, GET)
90 # global option
90 # global option
91 if fileid is None:
91 if fileid is None:
92 if ig_ws is None:
92 if ig_ws is None:
93 params['ignorews'] += [1]
93 params['ignorews'] += [1]
94 lbl = _('Ignore whitespace')
94 lbl = _('Ignore whitespace')
95 ctx_key = 'context'
95 ctx_key = 'context'
96 ctx_val = ln_ctx
96 ctx_val = ln_ctx
97 # per file options
97 # per file options
98 else:
98 else:
99 if ig_ws is None:
99 if ig_ws is None:
100 params[fileid] += ['WS:1']
100 params[fileid] += ['WS:1']
101 lbl = _('Ignore whitespace')
101 lbl = _('Ignore whitespace')
102
102
103 ctx_key = fileid
103 ctx_key = fileid
104 ctx_val = 'C:%s' % ln_ctx
104 ctx_val = 'C:%s' % ln_ctx
105 # if we have passed in ln_ctx pass it along to our params
105 # if we have passed in ln_ctx pass it along to our params
106 if ln_ctx:
106 if ln_ctx:
107 params[ctx_key] += [ctx_val]
107 params[ctx_key] += [ctx_val]
108
108
109 params['anchor'] = fileid
109 params['anchor'] = fileid
110 icon = h.literal('<i class="icon-strike"></i>')
110 icon = h.literal('<i class="icon-strike"></i>')
111 return h.link_to(icon, h.url.current(**params), title=lbl, class_='tooltip')
111 return h.link_to(icon, h.url.current(**params), title=lbl, **{'data-toggle': 'tooltip'})
112
112
113
113
114 def get_line_ctx(fid, GET):
114 def get_line_ctx(fid, GET):
115 ln_ctx_global = GET.get('context')
115 ln_ctx_global = GET.get('context')
116 if fid:
116 if fid:
117 ln_ctx = filter(lambda k: k.startswith('C'), GET.getall(fid))
117 ln_ctx = filter(lambda k: k.startswith('C'), GET.getall(fid))
118 else:
118 else:
119 _ln_ctx = filter(lambda k: k.startswith('C'), GET)
119 _ln_ctx = filter(lambda k: k.startswith('C'), GET)
120 ln_ctx = GET.get(_ln_ctx[0]) if _ln_ctx else ln_ctx_global
120 ln_ctx = GET.get(_ln_ctx[0]) if _ln_ctx else ln_ctx_global
121 if ln_ctx:
121 if ln_ctx:
122 ln_ctx = [ln_ctx]
122 ln_ctx = [ln_ctx]
123
123
124 if ln_ctx:
124 if ln_ctx:
125 retval = ln_ctx[0].split(':')[-1]
125 retval = ln_ctx[0].split(':')[-1]
126 else:
126 else:
127 retval = ln_ctx_global
127 retval = ln_ctx_global
128
128
129 try:
129 try:
130 return int(retval)
130 return int(retval)
131 except Exception:
131 except Exception:
132 return 3
132 return 3
133
133
134
134
135 def _context_url(GET, fileid=None):
135 def _context_url(GET, fileid=None):
136 """
136 """
137 Generates url for context lines
137 Generates url for context lines
138
138
139 :param fileid:
139 :param fileid:
140 """
140 """
141
141
142 fileid = str(fileid) if fileid else None
142 fileid = str(fileid) if fileid else None
143 ig_ws = get_ignore_ws(fileid, GET)
143 ig_ws = get_ignore_ws(fileid, GET)
144 ln_ctx = (get_line_ctx(fileid, GET) or 3) * 2
144 ln_ctx = (get_line_ctx(fileid, GET) or 3) * 2
145
145
146 params = defaultdict(list)
146 params = defaultdict(list)
147 _update_with_GET(params, GET)
147 _update_with_GET(params, GET)
148
148
149 # global option
149 # global option
150 if fileid is None:
150 if fileid is None:
151 if ln_ctx > 0:
151 if ln_ctx > 0:
152 params['context'] += [ln_ctx]
152 params['context'] += [ln_ctx]
153
153
154 if ig_ws:
154 if ig_ws:
155 ig_ws_key = 'ignorews'
155 ig_ws_key = 'ignorews'
156 ig_ws_val = 1
156 ig_ws_val = 1
157
157
158 # per file option
158 # per file option
159 else:
159 else:
160 params[fileid] += ['C:%s' % ln_ctx]
160 params[fileid] += ['C:%s' % ln_ctx]
161 ig_ws_key = fileid
161 ig_ws_key = fileid
162 ig_ws_val = 'WS:%s' % 1
162 ig_ws_val = 'WS:%s' % 1
163
163
164 if ig_ws:
164 if ig_ws:
165 params[ig_ws_key] += [ig_ws_val]
165 params[ig_ws_key] += [ig_ws_val]
166
166
167 lbl = _('Increase diff context to %(num)s lines') % {'num': ln_ctx}
167 lbl = _('Increase diff context to %(num)s lines') % {'num': ln_ctx}
168
168
169 params['anchor'] = fileid
169 params['anchor'] = fileid
170 icon = h.literal('<i class="icon-sort"></i>')
170 icon = h.literal('<i class="icon-sort"></i>')
171 return h.link_to(icon, h.url.current(**params), title=lbl, class_='tooltip')
171 return h.link_to(icon, h.url.current(**params), title=lbl, **{'data-toggle': 'tooltip'})
172
172
173
173
174 # Could perhaps be nice to have in the model but is too high level ...
174 # Could perhaps be nice to have in the model but is too high level ...
175 def create_comment(text, status, f_path, line_no, revision=None, pull_request_id=None, closing_pr=None):
175 def create_comment(text, status, f_path, line_no, revision=None, pull_request_id=None, closing_pr=None):
176 """Comment functionality shared between changesets and pullrequests"""
176 """Comment functionality shared between changesets and pullrequests"""
177 f_path = f_path or None
177 f_path = f_path or None
178 line_no = line_no or None
178 line_no = line_no or None
179
179
180 comment = ChangesetCommentsModel().create(
180 comment = ChangesetCommentsModel().create(
181 text=text,
181 text=text,
182 repo=c.db_repo.repo_id,
182 repo=c.db_repo.repo_id,
183 author=c.authuser.user_id,
183 author=c.authuser.user_id,
184 revision=revision,
184 revision=revision,
185 pull_request=pull_request_id,
185 pull_request=pull_request_id,
186 f_path=f_path,
186 f_path=f_path,
187 line_no=line_no,
187 line_no=line_no,
188 status_change=ChangesetStatus.get_status_lbl(status) if status else None,
188 status_change=ChangesetStatus.get_status_lbl(status) if status else None,
189 closing_pr=closing_pr,
189 closing_pr=closing_pr,
190 )
190 )
191
191
192 return comment
192 return comment
193
193
194
194
195 class ChangesetController(BaseRepoController):
195 class ChangesetController(BaseRepoController):
196
196
197 def __before__(self):
197 def __before__(self):
198 super(ChangesetController, self).__before__()
198 super(ChangesetController, self).__before__()
199 c.affected_files_cut_off = 60
199 c.affected_files_cut_off = 60
200
200
201 def __load_data(self):
201 def __load_data(self):
202 repo_model = RepoModel()
202 repo_model = RepoModel()
203 c.users_array = repo_model.get_users_js()
203 c.users_array = repo_model.get_users_js()
204 c.user_groups_array = repo_model.get_user_groups_js()
204 c.user_groups_array = repo_model.get_user_groups_js()
205
205
206 def _index(self, revision, method):
206 def _index(self, revision, method):
207 c.pull_request = None
207 c.pull_request = None
208 c.anchor_url = anchor_url
208 c.anchor_url = anchor_url
209 c.ignorews_url = _ignorews_url
209 c.ignorews_url = _ignorews_url
210 c.context_url = _context_url
210 c.context_url = _context_url
211 c.fulldiff = fulldiff = request.GET.get('fulldiff')
211 c.fulldiff = fulldiff = request.GET.get('fulldiff')
212 #get ranges of revisions if preset
212 #get ranges of revisions if preset
213 rev_range = revision.split('...')[:2]
213 rev_range = revision.split('...')[:2]
214 enable_comments = True
214 enable_comments = True
215 c.cs_repo = c.db_repo
215 c.cs_repo = c.db_repo
216 try:
216 try:
217 if len(rev_range) == 2:
217 if len(rev_range) == 2:
218 enable_comments = False
218 enable_comments = False
219 rev_start = rev_range[0]
219 rev_start = rev_range[0]
220 rev_end = rev_range[1]
220 rev_end = rev_range[1]
221 rev_ranges = c.db_repo_scm_instance.get_changesets(start=rev_start,
221 rev_ranges = c.db_repo_scm_instance.get_changesets(start=rev_start,
222 end=rev_end)
222 end=rev_end)
223 else:
223 else:
224 rev_ranges = [c.db_repo_scm_instance.get_changeset(revision)]
224 rev_ranges = [c.db_repo_scm_instance.get_changeset(revision)]
225
225
226 c.cs_ranges = list(rev_ranges)
226 c.cs_ranges = list(rev_ranges)
227 if not c.cs_ranges:
227 if not c.cs_ranges:
228 raise RepositoryError('Changeset range returned empty result')
228 raise RepositoryError('Changeset range returned empty result')
229
229
230 except (ChangesetDoesNotExistError, EmptyRepositoryError):
230 except (ChangesetDoesNotExistError, EmptyRepositoryError):
231 log.debug(traceback.format_exc())
231 log.debug(traceback.format_exc())
232 msg = _('Such revision does not exist for this repository')
232 msg = _('Such revision does not exist for this repository')
233 h.flash(msg, category='error')
233 h.flash(msg, category='error')
234 raise HTTPNotFound()
234 raise HTTPNotFound()
235
235
236 c.changes = OrderedDict()
236 c.changes = OrderedDict()
237
237
238 c.lines_added = 0 # count of lines added
238 c.lines_added = 0 # count of lines added
239 c.lines_deleted = 0 # count of lines removes
239 c.lines_deleted = 0 # count of lines removes
240
240
241 c.changeset_statuses = ChangesetStatus.STATUSES
241 c.changeset_statuses = ChangesetStatus.STATUSES
242 comments = dict()
242 comments = dict()
243 c.statuses = []
243 c.statuses = []
244 c.inline_comments = []
244 c.inline_comments = []
245 c.inline_cnt = 0
245 c.inline_cnt = 0
246
246
247 # Iterate over ranges (default changeset view is always one changeset)
247 # Iterate over ranges (default changeset view is always one changeset)
248 for changeset in c.cs_ranges:
248 for changeset in c.cs_ranges:
249 if method == 'show':
249 if method == 'show':
250 c.statuses.extend([ChangesetStatusModel().get_status(
250 c.statuses.extend([ChangesetStatusModel().get_status(
251 c.db_repo.repo_id, changeset.raw_id)])
251 c.db_repo.repo_id, changeset.raw_id)])
252
252
253 # Changeset comments
253 # Changeset comments
254 comments.update((com.comment_id, com)
254 comments.update((com.comment_id, com)
255 for com in ChangesetCommentsModel()
255 for com in ChangesetCommentsModel()
256 .get_comments(c.db_repo.repo_id,
256 .get_comments(c.db_repo.repo_id,
257 revision=changeset.raw_id))
257 revision=changeset.raw_id))
258
258
259 # Status change comments - mostly from pull requests
259 # Status change comments - mostly from pull requests
260 comments.update((st.comment_id, st.comment)
260 comments.update((st.comment_id, st.comment)
261 for st in ChangesetStatusModel()
261 for st in ChangesetStatusModel()
262 .get_statuses(c.db_repo.repo_id,
262 .get_statuses(c.db_repo.repo_id,
263 changeset.raw_id, with_revisions=True)
263 changeset.raw_id, with_revisions=True)
264 if st.comment_id is not None)
264 if st.comment_id is not None)
265
265
266 inlines = ChangesetCommentsModel() \
266 inlines = ChangesetCommentsModel() \
267 .get_inline_comments(c.db_repo.repo_id,
267 .get_inline_comments(c.db_repo.repo_id,
268 revision=changeset.raw_id)
268 revision=changeset.raw_id)
269 c.inline_comments.extend(inlines)
269 c.inline_comments.extend(inlines)
270
270
271 cs2 = changeset.raw_id
271 cs2 = changeset.raw_id
272 cs1 = changeset.parents[0].raw_id if changeset.parents else EmptyChangeset().raw_id
272 cs1 = changeset.parents[0].raw_id if changeset.parents else EmptyChangeset().raw_id
273 context_lcl = get_line_ctx('', request.GET)
273 context_lcl = get_line_ctx('', request.GET)
274 ign_whitespace_lcl = get_ignore_ws('', request.GET)
274 ign_whitespace_lcl = get_ignore_ws('', request.GET)
275
275
276 _diff = c.db_repo_scm_instance.get_diff(cs1, cs2,
276 _diff = c.db_repo_scm_instance.get_diff(cs1, cs2,
277 ignore_whitespace=ign_whitespace_lcl, context=context_lcl)
277 ignore_whitespace=ign_whitespace_lcl, context=context_lcl)
278 diff_limit = self.cut_off_limit if not fulldiff else None
278 diff_limit = self.cut_off_limit if not fulldiff else None
279 diff_processor = diffs.DiffProcessor(_diff,
279 diff_processor = diffs.DiffProcessor(_diff,
280 vcs=c.db_repo_scm_instance.alias,
280 vcs=c.db_repo_scm_instance.alias,
281 format='gitdiff',
281 format='gitdiff',
282 diff_limit=diff_limit)
282 diff_limit=diff_limit)
283 file_diff_data = []
283 file_diff_data = []
284 if method == 'show':
284 if method == 'show':
285 _parsed = diff_processor.prepare()
285 _parsed = diff_processor.prepare()
286 c.limited_diff = False
286 c.limited_diff = False
287 if isinstance(_parsed, LimitedDiffContainer):
287 if isinstance(_parsed, LimitedDiffContainer):
288 c.limited_diff = True
288 c.limited_diff = True
289 for f in _parsed:
289 for f in _parsed:
290 st = f['stats']
290 st = f['stats']
291 c.lines_added += st['added']
291 c.lines_added += st['added']
292 c.lines_deleted += st['deleted']
292 c.lines_deleted += st['deleted']
293 filename = f['filename']
293 filename = f['filename']
294 fid = h.FID(changeset.raw_id, filename)
294 fid = h.FID(changeset.raw_id, filename)
295 url_fid = h.FID('', filename)
295 url_fid = h.FID('', filename)
296 diff = diff_processor.as_html(enable_comments=enable_comments,
296 diff = diff_processor.as_html(enable_comments=enable_comments,
297 parsed_lines=[f])
297 parsed_lines=[f])
298 file_diff_data.append((fid, url_fid, f['operation'], f['old_filename'], filename, diff, st))
298 file_diff_data.append((fid, url_fid, f['operation'], f['old_filename'], filename, diff, st))
299 else:
299 else:
300 # downloads/raw we only need RAW diff nothing else
300 # downloads/raw we only need RAW diff nothing else
301 diff = diff_processor.as_raw()
301 diff = diff_processor.as_raw()
302 file_diff_data.append(('', None, None, None, diff, None))
302 file_diff_data.append(('', None, None, None, diff, None))
303 c.changes[changeset.raw_id] = (cs1, cs2, file_diff_data)
303 c.changes[changeset.raw_id] = (cs1, cs2, file_diff_data)
304
304
305 #sort comments in creation order
305 #sort comments in creation order
306 c.comments = [com for com_id, com in sorted(comments.items())]
306 c.comments = [com for com_id, com in sorted(comments.items())]
307
307
308 # count inline comments
308 # count inline comments
309 for __, lines in c.inline_comments:
309 for __, lines in c.inline_comments:
310 for comments in lines.values():
310 for comments in lines.values():
311 c.inline_cnt += len(comments)
311 c.inline_cnt += len(comments)
312
312
313 if len(c.cs_ranges) == 1:
313 if len(c.cs_ranges) == 1:
314 c.changeset = c.cs_ranges[0]
314 c.changeset = c.cs_ranges[0]
315 c.parent_tmpl = ''.join(['# Parent %s\n' % x.raw_id
315 c.parent_tmpl = ''.join(['# Parent %s\n' % x.raw_id
316 for x in c.changeset.parents])
316 for x in c.changeset.parents])
317 if method == 'download':
317 if method == 'download':
318 response.content_type = 'text/plain'
318 response.content_type = 'text/plain'
319 response.content_disposition = 'attachment; filename=%s.diff' \
319 response.content_disposition = 'attachment; filename=%s.diff' \
320 % revision[:12]
320 % revision[:12]
321 return diff
321 return diff
322 elif method == 'patch':
322 elif method == 'patch':
323 response.content_type = 'text/plain'
323 response.content_type = 'text/plain'
324 c.diff = safe_unicode(diff)
324 c.diff = safe_unicode(diff)
325 return render('changeset/patch_changeset.html')
325 return render('changeset/patch_changeset.html')
326 elif method == 'raw':
326 elif method == 'raw':
327 response.content_type = 'text/plain'
327 response.content_type = 'text/plain'
328 return diff
328 return diff
329 elif method == 'show':
329 elif method == 'show':
330 self.__load_data()
330 self.__load_data()
331 if len(c.cs_ranges) == 1:
331 if len(c.cs_ranges) == 1:
332 return render('changeset/changeset.html')
332 return render('changeset/changeset.html')
333 else:
333 else:
334 c.cs_ranges_org = None
334 c.cs_ranges_org = None
335 c.cs_comments = {}
335 c.cs_comments = {}
336 revs = [ctx.revision for ctx in reversed(c.cs_ranges)]
336 revs = [ctx.revision for ctx in reversed(c.cs_ranges)]
337 c.jsdata = json.dumps(graph_data(c.db_repo_scm_instance, revs))
337 c.jsdata = json.dumps(graph_data(c.db_repo_scm_instance, revs))
338 return render('changeset/changeset_range.html')
338 return render('changeset/changeset_range.html')
339
339
340 @LoginRequired()
340 @LoginRequired()
341 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
341 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
342 'repository.admin')
342 'repository.admin')
343 def index(self, revision, method='show'):
343 def index(self, revision, method='show'):
344 return self._index(revision, method=method)
344 return self._index(revision, method=method)
345
345
346 @LoginRequired()
346 @LoginRequired()
347 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
347 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
348 'repository.admin')
348 'repository.admin')
349 def changeset_raw(self, revision):
349 def changeset_raw(self, revision):
350 return self._index(revision, method='raw')
350 return self._index(revision, method='raw')
351
351
352 @LoginRequired()
352 @LoginRequired()
353 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
353 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
354 'repository.admin')
354 'repository.admin')
355 def changeset_patch(self, revision):
355 def changeset_patch(self, revision):
356 return self._index(revision, method='patch')
356 return self._index(revision, method='patch')
357
357
358 @LoginRequired()
358 @LoginRequired()
359 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
359 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
360 'repository.admin')
360 'repository.admin')
361 def changeset_download(self, revision):
361 def changeset_download(self, revision):
362 return self._index(revision, method='download')
362 return self._index(revision, method='download')
363
363
364 @LoginRequired()
364 @LoginRequired()
365 @NotAnonymous()
365 @NotAnonymous()
366 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
366 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
367 'repository.admin')
367 'repository.admin')
368 @jsonify
368 @jsonify
369 def comment(self, repo_name, revision):
369 def comment(self, repo_name, revision):
370 assert request.environ.get('HTTP_X_PARTIAL_XHR')
370 assert request.environ.get('HTTP_X_PARTIAL_XHR')
371
371
372 status = request.POST.get('changeset_status')
372 status = request.POST.get('changeset_status')
373 text = request.POST.get('text', '').strip()
373 text = request.POST.get('text', '').strip()
374
374
375 c.comment = create_comment(
375 c.comment = create_comment(
376 text,
376 text,
377 status,
377 status,
378 revision=revision,
378 revision=revision,
379 f_path=request.POST.get('f_path'),
379 f_path=request.POST.get('f_path'),
380 line_no=request.POST.get('line'),
380 line_no=request.POST.get('line'),
381 )
381 )
382
382
383 # get status if set !
383 # get status if set !
384 if status:
384 if status:
385 # if latest status was from pull request and it's closed
385 # if latest status was from pull request and it's closed
386 # disallow changing status ! RLY?
386 # disallow changing status ! RLY?
387 try:
387 try:
388 ChangesetStatusModel().set_status(
388 ChangesetStatusModel().set_status(
389 c.db_repo.repo_id,
389 c.db_repo.repo_id,
390 status,
390 status,
391 c.authuser.user_id,
391 c.authuser.user_id,
392 c.comment,
392 c.comment,
393 revision=revision,
393 revision=revision,
394 dont_allow_on_closed_pull_request=True,
394 dont_allow_on_closed_pull_request=True,
395 )
395 )
396 except StatusChangeOnClosedPullRequestError:
396 except StatusChangeOnClosedPullRequestError:
397 log.debug('cannot change status on %s with closed pull request', revision)
397 log.debug('cannot change status on %s with closed pull request', revision)
398 raise HTTPBadRequest()
398 raise HTTPBadRequest()
399
399
400 action_logger(self.authuser,
400 action_logger(self.authuser,
401 'user_commented_revision:%s' % revision,
401 'user_commented_revision:%s' % revision,
402 c.db_repo, self.ip_addr, self.sa)
402 c.db_repo, self.ip_addr, self.sa)
403
403
404 Session().commit()
404 Session().commit()
405
405
406 data = {
406 data = {
407 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))),
407 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))),
408 }
408 }
409 if c.comment is not None:
409 if c.comment is not None:
410 data.update(c.comment.get_dict())
410 data.update(c.comment.get_dict())
411 data.update({'rendered_text':
411 data.update({'rendered_text':
412 render('changeset/changeset_comment_block.html')})
412 render('changeset/changeset_comment_block.html')})
413
413
414 return data
414 return data
415
415
416 @LoginRequired()
416 @LoginRequired()
417 @NotAnonymous()
417 @NotAnonymous()
418 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
418 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
419 'repository.admin')
419 'repository.admin')
420 @jsonify
420 @jsonify
421 def delete_comment(self, repo_name, comment_id):
421 def delete_comment(self, repo_name, comment_id):
422 co = ChangesetComment.get_or_404(comment_id)
422 co = ChangesetComment.get_or_404(comment_id)
423 if co.repo.repo_name != repo_name:
423 if co.repo.repo_name != repo_name:
424 raise HTTPNotFound()
424 raise HTTPNotFound()
425 owner = co.author_id == c.authuser.user_id
425 owner = co.author_id == c.authuser.user_id
426 repo_admin = h.HasRepoPermissionAny('repository.admin')(repo_name)
426 repo_admin = h.HasRepoPermissionAny('repository.admin')(repo_name)
427 if h.HasPermissionAny('hg.admin')() or repo_admin or owner:
427 if h.HasPermissionAny('hg.admin')() or repo_admin or owner:
428 ChangesetCommentsModel().delete(comment=co)
428 ChangesetCommentsModel().delete(comment=co)
429 Session().commit()
429 Session().commit()
430 return True
430 return True
431 else:
431 else:
432 raise HTTPForbidden()
432 raise HTTPForbidden()
433
433
434 @LoginRequired()
434 @LoginRequired()
435 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
435 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
436 'repository.admin')
436 'repository.admin')
437 @jsonify
437 @jsonify
438 def changeset_info(self, repo_name, revision):
438 def changeset_info(self, repo_name, revision):
439 if request.is_xhr:
439 if request.is_xhr:
440 try:
440 try:
441 return c.db_repo_scm_instance.get_changeset(revision)
441 return c.db_repo_scm_instance.get_changeset(revision)
442 except ChangesetDoesNotExistError as e:
442 except ChangesetDoesNotExistError as e:
443 return EmptyChangeset(message=str(e))
443 return EmptyChangeset(message=str(e))
444 else:
444 else:
445 raise HTTPBadRequest()
445 raise HTTPBadRequest()
446
446
447 @LoginRequired()
447 @LoginRequired()
448 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
448 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
449 'repository.admin')
449 'repository.admin')
450 @jsonify
450 @jsonify
451 def changeset_children(self, repo_name, revision):
451 def changeset_children(self, repo_name, revision):
452 if request.is_xhr:
452 if request.is_xhr:
453 changeset = c.db_repo_scm_instance.get_changeset(revision)
453 changeset = c.db_repo_scm_instance.get_changeset(revision)
454 result = {"results": []}
454 result = {"results": []}
455 if changeset.children:
455 if changeset.children:
456 result = {"results": changeset.children}
456 result = {"results": changeset.children}
457 return result
457 return result
458 else:
458 else:
459 raise HTTPBadRequest()
459 raise HTTPBadRequest()
460
460
461 @LoginRequired()
461 @LoginRequired()
462 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
462 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
463 'repository.admin')
463 'repository.admin')
464 @jsonify
464 @jsonify
465 def changeset_parents(self, repo_name, revision):
465 def changeset_parents(self, repo_name, revision):
466 if request.is_xhr:
466 if request.is_xhr:
467 changeset = c.db_repo_scm_instance.get_changeset(revision)
467 changeset = c.db_repo_scm_instance.get_changeset(revision)
468 result = {"results": []}
468 result = {"results": []}
469 if changeset.parents:
469 if changeset.parents:
470 result = {"results": changeset.parents}
470 result = {"results": changeset.parents}
471 return result
471 return result
472 else:
472 else:
473 raise HTTPBadRequest()
473 raise HTTPBadRequest()
@@ -1,1205 +1,1204 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 # This program is free software: you can redistribute it and/or modify
2 # This program is free software: you can redistribute it and/or modify
3 # it under the terms of the GNU General Public License as published by
3 # it under the terms of the GNU General Public License as published by
4 # the Free Software Foundation, either version 3 of the License, or
4 # the Free Software Foundation, either version 3 of the License, or
5 # (at your option) any later version.
5 # (at your option) any later version.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU General Public License
12 # You should have received a copy of the GNU General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 """
14 """
15 Helper functions
15 Helper functions
16
16
17 Consists of functions to typically be used within templates, but also
17 Consists of functions to typically be used within templates, but also
18 available to Controllers. This module is available to both as 'h'.
18 available to Controllers. This module is available to both as 'h'.
19 """
19 """
20 import hashlib
20 import hashlib
21 import StringIO
21 import StringIO
22 import logging
22 import logging
23 import re
23 import re
24 import urlparse
24 import urlparse
25 import textwrap
25 import textwrap
26
26
27 from beaker.cache import cache_region
27 from beaker.cache import cache_region
28 from pygments.formatters.html import HtmlFormatter
28 from pygments.formatters.html import HtmlFormatter
29 from pygments import highlight as code_highlight
29 from pygments import highlight as code_highlight
30 from pylons.i18n.translation import _
30 from pylons.i18n.translation import _
31
31
32 from webhelpers.html import literal, HTML, escape
32 from webhelpers.html import literal, HTML, escape
33 from webhelpers.html.tags import checkbox, end_form, hidden, link_to, \
33 from webhelpers.html.tags import checkbox, end_form, hidden, link_to, \
34 select, submit, text, password, textarea, radio, form as insecure_form
34 select, submit, text, password, textarea, radio, form as insecure_form
35 from webhelpers.number import format_byte_size
35 from webhelpers.number import format_byte_size
36 from webhelpers.pylonslib import Flash as _Flash
36 from webhelpers.pylonslib import Flash as _Flash
37 from webhelpers.pylonslib.secure_form import secure_form, authentication_token
37 from webhelpers.pylonslib.secure_form import secure_form, authentication_token
38 from webhelpers.text import chop_at, truncate, wrap_paragraphs
38 from webhelpers.text import chop_at, truncate, wrap_paragraphs
39 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
39 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
40 convert_boolean_attrs, NotGiven, _make_safe_id_component
40 convert_boolean_attrs, NotGiven, _make_safe_id_component
41
41
42 from kallithea.config.routing import url
42 from kallithea.config.routing import url
43 from kallithea.lib.annotate import annotate_highlight
43 from kallithea.lib.annotate import annotate_highlight
44 from kallithea.lib.pygmentsutils import get_custom_lexer
44 from kallithea.lib.pygmentsutils import get_custom_lexer
45 from kallithea.lib.utils2 import str2bool, safe_unicode, safe_str, \
45 from kallithea.lib.utils2 import str2bool, safe_unicode, safe_str, \
46 time_to_datetime, AttributeDict, safe_int, MENTIONS_REGEX
46 time_to_datetime, AttributeDict, safe_int, MENTIONS_REGEX
47 from kallithea.lib.markup_renderer import url_re
47 from kallithea.lib.markup_renderer import url_re
48 from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError
48 from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError
49 from kallithea.lib.vcs.backends.base import BaseChangeset, EmptyChangeset
49 from kallithea.lib.vcs.backends.base import BaseChangeset, EmptyChangeset
50
50
51 log = logging.getLogger(__name__)
51 log = logging.getLogger(__name__)
52
52
53
53
54 def canonical_url(*args, **kargs):
54 def canonical_url(*args, **kargs):
55 '''Like url(x, qualified=True), but returns url that not only is qualified
55 '''Like url(x, qualified=True), but returns url that not only is qualified
56 but also canonical, as configured in canonical_url'''
56 but also canonical, as configured in canonical_url'''
57 from kallithea import CONFIG
57 from kallithea import CONFIG
58 try:
58 try:
59 parts = CONFIG.get('canonical_url', '').split('://', 1)
59 parts = CONFIG.get('canonical_url', '').split('://', 1)
60 kargs['host'] = parts[1].split('/', 1)[0]
60 kargs['host'] = parts[1].split('/', 1)[0]
61 kargs['protocol'] = parts[0]
61 kargs['protocol'] = parts[0]
62 except IndexError:
62 except IndexError:
63 kargs['qualified'] = True
63 kargs['qualified'] = True
64 return url(*args, **kargs)
64 return url(*args, **kargs)
65
65
66 def canonical_hostname():
66 def canonical_hostname():
67 '''Return canonical hostname of system'''
67 '''Return canonical hostname of system'''
68 from kallithea import CONFIG
68 from kallithea import CONFIG
69 try:
69 try:
70 parts = CONFIG.get('canonical_url', '').split('://', 1)
70 parts = CONFIG.get('canonical_url', '').split('://', 1)
71 return parts[1].split('/', 1)[0]
71 return parts[1].split('/', 1)[0]
72 except IndexError:
72 except IndexError:
73 parts = url('home', qualified=True).split('://', 1)
73 parts = url('home', qualified=True).split('://', 1)
74 return parts[1].split('/', 1)[0]
74 return parts[1].split('/', 1)[0]
75
75
76 def html_escape(s):
76 def html_escape(s):
77 """Return string with all html escaped.
77 """Return string with all html escaped.
78 This is also safe for javascript in html but not necessarily correct.
78 This is also safe for javascript in html but not necessarily correct.
79 """
79 """
80 return (s
80 return (s
81 .replace('&', '&amp;')
81 .replace('&', '&amp;')
82 .replace(">", "&gt;")
82 .replace(">", "&gt;")
83 .replace("<", "&lt;")
83 .replace("<", "&lt;")
84 .replace('"', "&quot;")
84 .replace('"', "&quot;")
85 .replace("'", "&apos;")
85 .replace("'", "&apos;")
86 )
86 )
87
87
88 def shorter(s, size=20, firstline=False, postfix='...'):
88 def shorter(s, size=20, firstline=False, postfix='...'):
89 """Truncate s to size, including the postfix string if truncating.
89 """Truncate s to size, including the postfix string if truncating.
90 If firstline, truncate at newline.
90 If firstline, truncate at newline.
91 """
91 """
92 if firstline:
92 if firstline:
93 s = s.split('\n', 1)[0].rstrip()
93 s = s.split('\n', 1)[0].rstrip()
94 if len(s) > size:
94 if len(s) > size:
95 return s[:size - len(postfix)] + postfix
95 return s[:size - len(postfix)] + postfix
96 return s
96 return s
97
97
98
98
99 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
99 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
100 """
100 """
101 Reset button
101 Reset button
102 """
102 """
103 _set_input_attrs(attrs, type, name, value)
103 _set_input_attrs(attrs, type, name, value)
104 _set_id_attr(attrs, id, name)
104 _set_id_attr(attrs, id, name)
105 convert_boolean_attrs(attrs, ["disabled"])
105 convert_boolean_attrs(attrs, ["disabled"])
106 return HTML.input(**attrs)
106 return HTML.input(**attrs)
107
107
108 reset = _reset
108 reset = _reset
109 safeid = _make_safe_id_component
109 safeid = _make_safe_id_component
110
110
111
111
112 def FID(raw_id, path):
112 def FID(raw_id, path):
113 """
113 """
114 Creates a unique ID for filenode based on it's hash of path and revision
114 Creates a unique ID for filenode based on it's hash of path and revision
115 it's safe to use in urls
115 it's safe to use in urls
116
116
117 :param raw_id:
117 :param raw_id:
118 :param path:
118 :param path:
119 """
119 """
120
120
121 return 'C-%s-%s' % (short_id(raw_id), hashlib.md5(safe_str(path)).hexdigest()[:12])
121 return 'C-%s-%s' % (short_id(raw_id), hashlib.md5(safe_str(path)).hexdigest()[:12])
122
122
123
123
124 class _FilesBreadCrumbs(object):
124 class _FilesBreadCrumbs(object):
125
125
126 def __call__(self, repo_name, rev, paths):
126 def __call__(self, repo_name, rev, paths):
127 if isinstance(paths, str):
127 if isinstance(paths, str):
128 paths = safe_unicode(paths)
128 paths = safe_unicode(paths)
129 url_l = [link_to(repo_name, url('files_home',
129 url_l = [link_to(repo_name, url('files_home',
130 repo_name=repo_name,
130 repo_name=repo_name,
131 revision=rev, f_path=''),
131 revision=rev, f_path=''),
132 class_='ypjax-link')]
132 class_='ypjax-link')]
133 paths_l = paths.split('/')
133 paths_l = paths.split('/')
134 for cnt, p in enumerate(paths_l):
134 for cnt, p in enumerate(paths_l):
135 if p != '':
135 if p != '':
136 url_l.append(link_to(p,
136 url_l.append(link_to(p,
137 url('files_home',
137 url('files_home',
138 repo_name=repo_name,
138 repo_name=repo_name,
139 revision=rev,
139 revision=rev,
140 f_path='/'.join(paths_l[:cnt + 1])
140 f_path='/'.join(paths_l[:cnt + 1])
141 ),
141 ),
142 class_='ypjax-link'
142 class_='ypjax-link'
143 )
143 )
144 )
144 )
145
145
146 return literal('/'.join(url_l))
146 return literal('/'.join(url_l))
147
147
148 files_breadcrumbs = _FilesBreadCrumbs()
148 files_breadcrumbs = _FilesBreadCrumbs()
149
149
150
150
151 class CodeHtmlFormatter(HtmlFormatter):
151 class CodeHtmlFormatter(HtmlFormatter):
152 """
152 """
153 My code Html Formatter for source codes
153 My code Html Formatter for source codes
154 """
154 """
155
155
156 def wrap(self, source, outfile):
156 def wrap(self, source, outfile):
157 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
157 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
158
158
159 def _wrap_code(self, source):
159 def _wrap_code(self, source):
160 for cnt, it in enumerate(source):
160 for cnt, it in enumerate(source):
161 i, t = it
161 i, t = it
162 t = '<span id="L%s">%s</span>' % (cnt + 1, t)
162 t = '<span id="L%s">%s</span>' % (cnt + 1, t)
163 yield i, t
163 yield i, t
164
164
165 def _wrap_tablelinenos(self, inner):
165 def _wrap_tablelinenos(self, inner):
166 dummyoutfile = StringIO.StringIO()
166 dummyoutfile = StringIO.StringIO()
167 lncount = 0
167 lncount = 0
168 for t, line in inner:
168 for t, line in inner:
169 if t:
169 if t:
170 lncount += 1
170 lncount += 1
171 dummyoutfile.write(line)
171 dummyoutfile.write(line)
172
172
173 fl = self.linenostart
173 fl = self.linenostart
174 mw = len(str(lncount + fl - 1))
174 mw = len(str(lncount + fl - 1))
175 sp = self.linenospecial
175 sp = self.linenospecial
176 st = self.linenostep
176 st = self.linenostep
177 la = self.lineanchors
177 la = self.lineanchors
178 aln = self.anchorlinenos
178 aln = self.anchorlinenos
179 nocls = self.noclasses
179 nocls = self.noclasses
180 if sp:
180 if sp:
181 lines = []
181 lines = []
182
182
183 for i in range(fl, fl + lncount):
183 for i in range(fl, fl + lncount):
184 if i % st == 0:
184 if i % st == 0:
185 if i % sp == 0:
185 if i % sp == 0:
186 if aln:
186 if aln:
187 lines.append('<a href="#%s%d" class="special">%*d</a>' %
187 lines.append('<a href="#%s%d" class="special">%*d</a>' %
188 (la, i, mw, i))
188 (la, i, mw, i))
189 else:
189 else:
190 lines.append('<span class="special">%*d</span>' % (mw, i))
190 lines.append('<span class="special">%*d</span>' % (mw, i))
191 else:
191 else:
192 if aln:
192 if aln:
193 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
193 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
194 else:
194 else:
195 lines.append('%*d' % (mw, i))
195 lines.append('%*d' % (mw, i))
196 else:
196 else:
197 lines.append('')
197 lines.append('')
198 ls = '\n'.join(lines)
198 ls = '\n'.join(lines)
199 else:
199 else:
200 lines = []
200 lines = []
201 for i in range(fl, fl + lncount):
201 for i in range(fl, fl + lncount):
202 if i % st == 0:
202 if i % st == 0:
203 if aln:
203 if aln:
204 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
204 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
205 else:
205 else:
206 lines.append('%*d' % (mw, i))
206 lines.append('%*d' % (mw, i))
207 else:
207 else:
208 lines.append('')
208 lines.append('')
209 ls = '\n'.join(lines)
209 ls = '\n'.join(lines)
210
210
211 # in case you wonder about the seemingly redundant <div> here: since the
211 # in case you wonder about the seemingly redundant <div> here: since the
212 # content in the other cell also is wrapped in a div, some browsers in
212 # content in the other cell also is wrapped in a div, some browsers in
213 # some configurations seem to mess up the formatting...
213 # some configurations seem to mess up the formatting...
214 if nocls:
214 if nocls:
215 yield 0, ('<table class="%stable">' % self.cssclass +
215 yield 0, ('<table class="%stable">' % self.cssclass +
216 '<tr><td><div class="linenodiv" '
216 '<tr><td><div class="linenodiv" '
217 'style="background-color: #f0f0f0; padding-right: 10px">'
217 'style="background-color: #f0f0f0; padding-right: 10px">'
218 '<pre style="line-height: 125%">' +
218 '<pre style="line-height: 125%">' +
219 ls + '</pre></div></td><td id="hlcode" class="code">')
219 ls + '</pre></div></td><td id="hlcode" class="code">')
220 else:
220 else:
221 yield 0, ('<table class="%stable">' % self.cssclass +
221 yield 0, ('<table class="%stable">' % self.cssclass +
222 '<tr><td class="linenos"><div class="linenodiv"><pre>' +
222 '<tr><td class="linenos"><div class="linenodiv"><pre>' +
223 ls + '</pre></div></td><td id="hlcode" class="code">')
223 ls + '</pre></div></td><td id="hlcode" class="code">')
224 yield 0, dummyoutfile.getvalue()
224 yield 0, dummyoutfile.getvalue()
225 yield 0, '</td></tr></table>'
225 yield 0, '</td></tr></table>'
226
226
227
227
228 _whitespace_re = re.compile(r'(\t)|( )(?=\n|</div>)')
228 _whitespace_re = re.compile(r'(\t)|( )(?=\n|</div>)')
229
229
230 def _markup_whitespace(m):
230 def _markup_whitespace(m):
231 groups = m.groups()
231 groups = m.groups()
232 if groups[0]:
232 if groups[0]:
233 return '<u>\t</u>'
233 return '<u>\t</u>'
234 if groups[1]:
234 if groups[1]:
235 return ' <i></i>'
235 return ' <i></i>'
236
236
237 def markup_whitespace(s):
237 def markup_whitespace(s):
238 return _whitespace_re.sub(_markup_whitespace, s)
238 return _whitespace_re.sub(_markup_whitespace, s)
239
239
240 def pygmentize(filenode, **kwargs):
240 def pygmentize(filenode, **kwargs):
241 """
241 """
242 pygmentize function using pygments
242 pygmentize function using pygments
243
243
244 :param filenode:
244 :param filenode:
245 """
245 """
246 lexer = get_custom_lexer(filenode.extension) or filenode.lexer
246 lexer = get_custom_lexer(filenode.extension) or filenode.lexer
247 return literal(markup_whitespace(
247 return literal(markup_whitespace(
248 code_highlight(filenode.content, lexer, CodeHtmlFormatter(**kwargs))))
248 code_highlight(filenode.content, lexer, CodeHtmlFormatter(**kwargs))))
249
249
250
250
251 def pygmentize_annotation(repo_name, filenode, **kwargs):
251 def pygmentize_annotation(repo_name, filenode, **kwargs):
252 """
252 """
253 pygmentize function for annotation
253 pygmentize function for annotation
254
254
255 :param filenode:
255 :param filenode:
256 """
256 """
257
257
258 color_dict = {}
258 color_dict = {}
259
259
260 def gen_color(n=10000):
260 def gen_color(n=10000):
261 """generator for getting n of evenly distributed colors using
261 """generator for getting n of evenly distributed colors using
262 hsv color and golden ratio. It always return same order of colors
262 hsv color and golden ratio. It always return same order of colors
263
263
264 :returns: RGB tuple
264 :returns: RGB tuple
265 """
265 """
266
266
267 def hsv_to_rgb(h, s, v):
267 def hsv_to_rgb(h, s, v):
268 if s == 0.0:
268 if s == 0.0:
269 return v, v, v
269 return v, v, v
270 i = int(h * 6.0) # XXX assume int() truncates!
270 i = int(h * 6.0) # XXX assume int() truncates!
271 f = (h * 6.0) - i
271 f = (h * 6.0) - i
272 p = v * (1.0 - s)
272 p = v * (1.0 - s)
273 q = v * (1.0 - s * f)
273 q = v * (1.0 - s * f)
274 t = v * (1.0 - s * (1.0 - f))
274 t = v * (1.0 - s * (1.0 - f))
275 i = i % 6
275 i = i % 6
276 if i == 0:
276 if i == 0:
277 return v, t, p
277 return v, t, p
278 if i == 1:
278 if i == 1:
279 return q, v, p
279 return q, v, p
280 if i == 2:
280 if i == 2:
281 return p, v, t
281 return p, v, t
282 if i == 3:
282 if i == 3:
283 return p, q, v
283 return p, q, v
284 if i == 4:
284 if i == 4:
285 return t, p, v
285 return t, p, v
286 if i == 5:
286 if i == 5:
287 return v, p, q
287 return v, p, q
288
288
289 golden_ratio = 0.618033988749895
289 golden_ratio = 0.618033988749895
290 h = 0.22717784590367374
290 h = 0.22717784590367374
291
291
292 for _unused in xrange(n):
292 for _unused in xrange(n):
293 h += golden_ratio
293 h += golden_ratio
294 h %= 1
294 h %= 1
295 HSV_tuple = [h, 0.95, 0.95]
295 HSV_tuple = [h, 0.95, 0.95]
296 RGB_tuple = hsv_to_rgb(*HSV_tuple)
296 RGB_tuple = hsv_to_rgb(*HSV_tuple)
297 yield map(lambda x: str(int(x * 256)), RGB_tuple)
297 yield map(lambda x: str(int(x * 256)), RGB_tuple)
298
298
299 cgenerator = gen_color()
299 cgenerator = gen_color()
300
300
301 def get_color_string(cs):
301 def get_color_string(cs):
302 if cs in color_dict:
302 if cs in color_dict:
303 col = color_dict[cs]
303 col = color_dict[cs]
304 else:
304 else:
305 col = color_dict[cs] = cgenerator.next()
305 col = color_dict[cs] = cgenerator.next()
306 return "color: rgb(%s)! important;" % (', '.join(col))
306 return "color: rgb(%s)! important;" % (', '.join(col))
307
307
308 def url_func(repo_name):
308 def url_func(repo_name):
309
309
310 def _url_func(changeset):
310 def _url_func(changeset):
311 author = escape(changeset.author)
311 author = escape(changeset.author)
312 date = changeset.date
312 date = changeset.date
313 message = escape(changeset.message)
313 message = escape(changeset.message)
314 tooltip_html = ("<div style='font-size:0.8em'><b>Author:</b>"
314 tooltip_html = ("<b>Author:</b> %s<br/>"
315 " %s<br/><b>Date:</b> %s</b><br/><b>Message:"
315 "<b>Date:</b> %s</b><br/>"
316 "</b> %s<br/></div>") % (author, date, message)
316 "<b>Message:</b> %s") % (author, date, message)
317
317
318 lnk_format = show_id(changeset)
318 lnk_format = show_id(changeset)
319 uri = link_to(
319 uri = link_to(
320 lnk_format,
320 lnk_format,
321 url('changeset_home', repo_name=repo_name,
321 url('changeset_home', repo_name=repo_name,
322 revision=changeset.raw_id),
322 revision=changeset.raw_id),
323 style=get_color_string(changeset.raw_id),
323 style=get_color_string(changeset.raw_id),
324 class_='safe-html-title',
324 **{'data-toggle': 'popover',
325 title=tooltip_html,
325 'data-content': tooltip_html}
326 **{'data-toggle': 'tooltip'}
327 )
326 )
328
327
329 uri += '\n'
328 uri += '\n'
330 return uri
329 return uri
331 return _url_func
330 return _url_func
332
331
333 return literal(markup_whitespace(annotate_highlight(filenode, url_func(repo_name), **kwargs)))
332 return literal(markup_whitespace(annotate_highlight(filenode, url_func(repo_name), **kwargs)))
334
333
335
334
336 class _Message(object):
335 class _Message(object):
337 """A message returned by ``Flash.pop_messages()``.
336 """A message returned by ``Flash.pop_messages()``.
338
337
339 Converting the message to a string returns the message text. Instances
338 Converting the message to a string returns the message text. Instances
340 also have the following attributes:
339 also have the following attributes:
341
340
342 * ``message``: the message text.
341 * ``message``: the message text.
343 * ``category``: the category specified when the message was created.
342 * ``category``: the category specified when the message was created.
344 """
343 """
345
344
346 def __init__(self, category, message):
345 def __init__(self, category, message):
347 self.category = category
346 self.category = category
348 self.message = message
347 self.message = message
349
348
350 def __str__(self):
349 def __str__(self):
351 return self.message
350 return self.message
352
351
353 __unicode__ = __str__
352 __unicode__ = __str__
354
353
355 def __html__(self):
354 def __html__(self):
356 return escape(safe_unicode(self.message))
355 return escape(safe_unicode(self.message))
357
356
358 class Flash(_Flash):
357 class Flash(_Flash):
359
358
360 def __call__(self, message, category=None, ignore_duplicate=False, logf=None):
359 def __call__(self, message, category=None, ignore_duplicate=False, logf=None):
361 """
360 """
362 Show a message to the user _and_ log it through the specified function
361 Show a message to the user _and_ log it through the specified function
363
362
364 category: notice (default), warning, error, success
363 category: notice (default), warning, error, success
365 logf: a custom log function - such as log.debug
364 logf: a custom log function - such as log.debug
366
365
367 logf defaults to log.info, unless category equals 'success', in which
366 logf defaults to log.info, unless category equals 'success', in which
368 case logf defaults to log.debug.
367 case logf defaults to log.debug.
369 """
368 """
370 if logf is None:
369 if logf is None:
371 logf = log.info
370 logf = log.info
372 if category == 'success':
371 if category == 'success':
373 logf = log.debug
372 logf = log.debug
374
373
375 logf('Flash %s: %s', category, message)
374 logf('Flash %s: %s', category, message)
376
375
377 super(Flash, self).__call__(message, category, ignore_duplicate)
376 super(Flash, self).__call__(message, category, ignore_duplicate)
378
377
379 def pop_messages(self):
378 def pop_messages(self):
380 """Return all accumulated messages and delete them from the session.
379 """Return all accumulated messages and delete them from the session.
381
380
382 The return value is a list of ``Message`` objects.
381 The return value is a list of ``Message`` objects.
383 """
382 """
384 from pylons import session
383 from pylons import session
385 messages = session.pop(self.session_key, [])
384 messages = session.pop(self.session_key, [])
386 session.save()
385 session.save()
387 return [_Message(*m) for m in messages]
386 return [_Message(*m) for m in messages]
388
387
389 flash = Flash()
388 flash = Flash()
390
389
391 #==============================================================================
390 #==============================================================================
392 # SCM FILTERS available via h.
391 # SCM FILTERS available via h.
393 #==============================================================================
392 #==============================================================================
394 from kallithea.lib.vcs.utils import author_name, author_email
393 from kallithea.lib.vcs.utils import author_name, author_email
395 from kallithea.lib.utils2 import credentials_filter, age as _age
394 from kallithea.lib.utils2 import credentials_filter, age as _age
396
395
397 age = lambda x, y=False: _age(x, y)
396 age = lambda x, y=False: _age(x, y)
398 capitalize = lambda x: x.capitalize()
397 capitalize = lambda x: x.capitalize()
399 email = author_email
398 email = author_email
400 short_id = lambda x: x[:12]
399 short_id = lambda x: x[:12]
401 hide_credentials = lambda x: ''.join(credentials_filter(x))
400 hide_credentials = lambda x: ''.join(credentials_filter(x))
402
401
403
402
404 def show_id(cs):
403 def show_id(cs):
405 """
404 """
406 Configurable function that shows ID
405 Configurable function that shows ID
407 by default it's r123:fffeeefffeee
406 by default it's r123:fffeeefffeee
408
407
409 :param cs: changeset instance
408 :param cs: changeset instance
410 """
409 """
411 from kallithea import CONFIG
410 from kallithea import CONFIG
412 def_len = safe_int(CONFIG.get('show_sha_length', 12))
411 def_len = safe_int(CONFIG.get('show_sha_length', 12))
413 show_rev = str2bool(CONFIG.get('show_revision_number', False))
412 show_rev = str2bool(CONFIG.get('show_revision_number', False))
414
413
415 raw_id = cs.raw_id[:def_len]
414 raw_id = cs.raw_id[:def_len]
416 if show_rev:
415 if show_rev:
417 return 'r%s:%s' % (cs.revision, raw_id)
416 return 'r%s:%s' % (cs.revision, raw_id)
418 else:
417 else:
419 return raw_id
418 return raw_id
420
419
421
420
422 def fmt_date(date):
421 def fmt_date(date):
423 if date:
422 if date:
424 return date.strftime("%Y-%m-%d %H:%M:%S").decode('utf8')
423 return date.strftime("%Y-%m-%d %H:%M:%S").decode('utf8')
425
424
426 return ""
425 return ""
427
426
428
427
429 def is_git(repository):
428 def is_git(repository):
430 if hasattr(repository, 'alias'):
429 if hasattr(repository, 'alias'):
431 _type = repository.alias
430 _type = repository.alias
432 elif hasattr(repository, 'repo_type'):
431 elif hasattr(repository, 'repo_type'):
433 _type = repository.repo_type
432 _type = repository.repo_type
434 else:
433 else:
435 _type = repository
434 _type = repository
436 return _type == 'git'
435 return _type == 'git'
437
436
438
437
439 def is_hg(repository):
438 def is_hg(repository):
440 if hasattr(repository, 'alias'):
439 if hasattr(repository, 'alias'):
441 _type = repository.alias
440 _type = repository.alias
442 elif hasattr(repository, 'repo_type'):
441 elif hasattr(repository, 'repo_type'):
443 _type = repository.repo_type
442 _type = repository.repo_type
444 else:
443 else:
445 _type = repository
444 _type = repository
446 return _type == 'hg'
445 return _type == 'hg'
447
446
448
447
449 @cache_region('long_term', 'user_or_none')
448 @cache_region('long_term', 'user_or_none')
450 def user_or_none(author):
449 def user_or_none(author):
451 """Try to match email part of VCS committer string with a local user - or return None"""
450 """Try to match email part of VCS committer string with a local user - or return None"""
452 from kallithea.model.db import User
451 from kallithea.model.db import User
453 email = author_email(author)
452 email = author_email(author)
454 if email:
453 if email:
455 return User.get_by_email(email, cache=True) # cache will only use sql_cache_short
454 return User.get_by_email(email, cache=True) # cache will only use sql_cache_short
456 return None
455 return None
457
456
458 def email_or_none(author):
457 def email_or_none(author):
459 """Try to match email part of VCS committer string with a local user.
458 """Try to match email part of VCS committer string with a local user.
460 Return primary email of user, email part of the specified author name, or None."""
459 Return primary email of user, email part of the specified author name, or None."""
461 if not author:
460 if not author:
462 return None
461 return None
463 user = user_or_none(author)
462 user = user_or_none(author)
464 if user is not None:
463 if user is not None:
465 return user.email # always use main email address - not necessarily the one used to find user
464 return user.email # always use main email address - not necessarily the one used to find user
466
465
467 # extract email from the commit string
466 # extract email from the commit string
468 email = author_email(author)
467 email = author_email(author)
469 if email:
468 if email:
470 return email
469 return email
471
470
472 # No valid email, not a valid user in the system, none!
471 # No valid email, not a valid user in the system, none!
473 return None
472 return None
474
473
475 def person(author, show_attr="username"):
474 def person(author, show_attr="username"):
476 """Find the user identified by 'author', return one of the users attributes,
475 """Find the user identified by 'author', return one of the users attributes,
477 default to the username attribute, None if there is no user"""
476 default to the username attribute, None if there is no user"""
478 from kallithea.model.db import User
477 from kallithea.model.db import User
479 # attr to return from fetched user
478 # attr to return from fetched user
480 person_getter = lambda usr: getattr(usr, show_attr)
479 person_getter = lambda usr: getattr(usr, show_attr)
481
480
482 # if author is already an instance use it for extraction
481 # if author is already an instance use it for extraction
483 if isinstance(author, User):
482 if isinstance(author, User):
484 return person_getter(author)
483 return person_getter(author)
485
484
486 user = user_or_none(author)
485 user = user_or_none(author)
487 if user is not None:
486 if user is not None:
488 return person_getter(user)
487 return person_getter(user)
489
488
490 # Still nothing? Just pass back the author name if any, else the email
489 # Still nothing? Just pass back the author name if any, else the email
491 return author_name(author) or email(author)
490 return author_name(author) or email(author)
492
491
493
492
494 def person_by_id(id_, show_attr="username"):
493 def person_by_id(id_, show_attr="username"):
495 from kallithea.model.db import User
494 from kallithea.model.db import User
496 # attr to return from fetched user
495 # attr to return from fetched user
497 person_getter = lambda usr: getattr(usr, show_attr)
496 person_getter = lambda usr: getattr(usr, show_attr)
498
497
499 #maybe it's an ID ?
498 #maybe it's an ID ?
500 if str(id_).isdigit() or isinstance(id_, int):
499 if str(id_).isdigit() or isinstance(id_, int):
501 id_ = int(id_)
500 id_ = int(id_)
502 user = User.get(id_)
501 user = User.get(id_)
503 if user is not None:
502 if user is not None:
504 return person_getter(user)
503 return person_getter(user)
505 return id_
504 return id_
506
505
507
506
508 def boolicon(value):
507 def boolicon(value):
509 """Returns boolean value of a value, represented as small html image of true/false
508 """Returns boolean value of a value, represented as small html image of true/false
510 icons
509 icons
511
510
512 :param value: value
511 :param value: value
513 """
512 """
514
513
515 if value:
514 if value:
516 return HTML.tag('i', class_="icon-ok")
515 return HTML.tag('i', class_="icon-ok")
517 else:
516 else:
518 return HTML.tag('i', class_="icon-minus-circled")
517 return HTML.tag('i', class_="icon-minus-circled")
519
518
520
519
521 def action_parser(user_log, feed=False, parse_cs=False):
520 def action_parser(user_log, feed=False, parse_cs=False):
522 """
521 """
523 This helper will action_map the specified string action into translated
522 This helper will action_map the specified string action into translated
524 fancy names with icons and links
523 fancy names with icons and links
525
524
526 :param user_log: user log instance
525 :param user_log: user log instance
527 :param feed: use output for feeds (no html and fancy icons)
526 :param feed: use output for feeds (no html and fancy icons)
528 :param parse_cs: parse Changesets into VCS instances
527 :param parse_cs: parse Changesets into VCS instances
529 """
528 """
530
529
531 action = user_log.action
530 action = user_log.action
532 action_params = ' '
531 action_params = ' '
533
532
534 x = action.split(':')
533 x = action.split(':')
535
534
536 if len(x) > 1:
535 if len(x) > 1:
537 action, action_params = x
536 action, action_params = x
538
537
539 def get_cs_links():
538 def get_cs_links():
540 revs_limit = 3 # display this amount always
539 revs_limit = 3 # display this amount always
541 revs_top_limit = 50 # show upto this amount of changesets hidden
540 revs_top_limit = 50 # show upto this amount of changesets hidden
542 revs_ids = action_params.split(',')
541 revs_ids = action_params.split(',')
543 deleted = user_log.repository is None
542 deleted = user_log.repository is None
544 if deleted:
543 if deleted:
545 return ','.join(revs_ids)
544 return ','.join(revs_ids)
546
545
547 repo_name = user_log.repository.repo_name
546 repo_name = user_log.repository.repo_name
548
547
549 def lnk(rev, repo_name):
548 def lnk(rev, repo_name):
550 lazy_cs = False
549 lazy_cs = False
551 title_ = None
550 title_ = None
552 url_ = '#'
551 url_ = '#'
553 if isinstance(rev, BaseChangeset) or isinstance(rev, AttributeDict):
552 if isinstance(rev, BaseChangeset) or isinstance(rev, AttributeDict):
554 if rev.op and rev.ref_name:
553 if rev.op and rev.ref_name:
555 if rev.op == 'delete_branch':
554 if rev.op == 'delete_branch':
556 lbl = _('Deleted branch: %s') % rev.ref_name
555 lbl = _('Deleted branch: %s') % rev.ref_name
557 elif rev.op == 'tag':
556 elif rev.op == 'tag':
558 lbl = _('Created tag: %s') % rev.ref_name
557 lbl = _('Created tag: %s') % rev.ref_name
559 else:
558 else:
560 lbl = 'Unknown operation %s' % rev.op
559 lbl = 'Unknown operation %s' % rev.op
561 else:
560 else:
562 lazy_cs = True
561 lazy_cs = True
563 lbl = rev.short_id[:8]
562 lbl = rev.short_id[:8]
564 url_ = url('changeset_home', repo_name=repo_name,
563 url_ = url('changeset_home', repo_name=repo_name,
565 revision=rev.raw_id)
564 revision=rev.raw_id)
566 else:
565 else:
567 # changeset cannot be found - it might have been stripped or removed
566 # changeset cannot be found - it might have been stripped or removed
568 lbl = rev[:12]
567 lbl = rev[:12]
569 title_ = _('Changeset %s not found') % lbl
568 title_ = _('Changeset %s not found') % lbl
570 if parse_cs:
569 if parse_cs:
571 return link_to(lbl, url_, title=title_, class_='tooltip')
570 return link_to(lbl, url_, title=title_, **{'data-toggle': 'tooltip'})
572 return link_to(lbl, url_, class_='lazy-cs' if lazy_cs else '',
571 return link_to(lbl, url_, class_='lazy-cs' if lazy_cs else '',
573 **{'data-raw_id':rev.raw_id, 'data-repo_name':repo_name})
572 **{'data-raw_id':rev.raw_id, 'data-repo_name':repo_name})
574
573
575 def _get_op(rev_txt):
574 def _get_op(rev_txt):
576 _op = None
575 _op = None
577 _name = rev_txt
576 _name = rev_txt
578 if len(rev_txt.split('=>')) == 2:
577 if len(rev_txt.split('=>')) == 2:
579 _op, _name = rev_txt.split('=>')
578 _op, _name = rev_txt.split('=>')
580 return _op, _name
579 return _op, _name
581
580
582 revs = []
581 revs = []
583 if len(filter(lambda v: v != '', revs_ids)) > 0:
582 if len(filter(lambda v: v != '', revs_ids)) > 0:
584 repo = None
583 repo = None
585 for rev in revs_ids[:revs_top_limit]:
584 for rev in revs_ids[:revs_top_limit]:
586 _op, _name = _get_op(rev)
585 _op, _name = _get_op(rev)
587
586
588 # we want parsed changesets, or new log store format is bad
587 # we want parsed changesets, or new log store format is bad
589 if parse_cs:
588 if parse_cs:
590 try:
589 try:
591 if repo is None:
590 if repo is None:
592 repo = user_log.repository.scm_instance
591 repo = user_log.repository.scm_instance
593 _rev = repo.get_changeset(rev)
592 _rev = repo.get_changeset(rev)
594 revs.append(_rev)
593 revs.append(_rev)
595 except ChangesetDoesNotExistError:
594 except ChangesetDoesNotExistError:
596 log.error('cannot find revision %s in this repo', rev)
595 log.error('cannot find revision %s in this repo', rev)
597 revs.append(rev)
596 revs.append(rev)
598 else:
597 else:
599 _rev = AttributeDict({
598 _rev = AttributeDict({
600 'short_id': rev[:12],
599 'short_id': rev[:12],
601 'raw_id': rev,
600 'raw_id': rev,
602 'message': '',
601 'message': '',
603 'op': _op,
602 'op': _op,
604 'ref_name': _name
603 'ref_name': _name
605 })
604 })
606 revs.append(_rev)
605 revs.append(_rev)
607 cs_links = [" " + ', '.join(
606 cs_links = [" " + ', '.join(
608 [lnk(rev, repo_name) for rev in revs[:revs_limit]]
607 [lnk(rev, repo_name) for rev in revs[:revs_limit]]
609 )]
608 )]
610 _op1, _name1 = _get_op(revs_ids[0])
609 _op1, _name1 = _get_op(revs_ids[0])
611 _op2, _name2 = _get_op(revs_ids[-1])
610 _op2, _name2 = _get_op(revs_ids[-1])
612
611
613 _rev = '%s...%s' % (_name1, _name2)
612 _rev = '%s...%s' % (_name1, _name2)
614
613
615 compare_view = (
614 compare_view = (
616 ' <div class="compare_view" data-toggle="tooltip" title="%s">'
615 ' <div class="compare_view" data-toggle="tooltip" title="%s">'
617 '<a href="%s">%s</a> </div>' % (
616 '<a href="%s">%s</a> </div>' % (
618 _('Show all combined changesets %s->%s') % (
617 _('Show all combined changesets %s->%s') % (
619 revs_ids[0][:12], revs_ids[-1][:12]
618 revs_ids[0][:12], revs_ids[-1][:12]
620 ),
619 ),
621 url('changeset_home', repo_name=repo_name,
620 url('changeset_home', repo_name=repo_name,
622 revision=_rev
621 revision=_rev
623 ),
622 ),
624 _('Compare view')
623 _('Compare view')
625 )
624 )
626 )
625 )
627
626
628 # if we have exactly one more than normally displayed
627 # if we have exactly one more than normally displayed
629 # just display it, takes less space than displaying
628 # just display it, takes less space than displaying
630 # "and 1 more revisions"
629 # "and 1 more revisions"
631 if len(revs_ids) == revs_limit + 1:
630 if len(revs_ids) == revs_limit + 1:
632 cs_links.append(", " + lnk(revs[revs_limit], repo_name))
631 cs_links.append(", " + lnk(revs[revs_limit], repo_name))
633
632
634 # hidden-by-default ones
633 # hidden-by-default ones
635 if len(revs_ids) > revs_limit + 1:
634 if len(revs_ids) > revs_limit + 1:
636 uniq_id = revs_ids[0]
635 uniq_id = revs_ids[0]
637 html_tmpl = (
636 html_tmpl = (
638 '<span> %s <a class="show_more" id="_%s" '
637 '<span> %s <a class="show_more" id="_%s" '
639 'href="#more">%s</a> %s</span>'
638 'href="#more">%s</a> %s</span>'
640 )
639 )
641 if not feed:
640 if not feed:
642 cs_links.append(html_tmpl % (
641 cs_links.append(html_tmpl % (
643 _('and'),
642 _('and'),
644 uniq_id, _('%s more') % (len(revs_ids) - revs_limit),
643 uniq_id, _('%s more') % (len(revs_ids) - revs_limit),
645 _('revisions')
644 _('revisions')
646 )
645 )
647 )
646 )
648
647
649 if not feed:
648 if not feed:
650 html_tmpl = '<span id="%s" style="display:none">, %s </span>'
649 html_tmpl = '<span id="%s" style="display:none">, %s </span>'
651 else:
650 else:
652 html_tmpl = '<span id="%s"> %s </span>'
651 html_tmpl = '<span id="%s"> %s </span>'
653
652
654 morelinks = ', '.join(
653 morelinks = ', '.join(
655 [lnk(rev, repo_name) for rev in revs[revs_limit:]]
654 [lnk(rev, repo_name) for rev in revs[revs_limit:]]
656 )
655 )
657
656
658 if len(revs_ids) > revs_top_limit:
657 if len(revs_ids) > revs_top_limit:
659 morelinks += ', ...'
658 morelinks += ', ...'
660
659
661 cs_links.append(html_tmpl % (uniq_id, morelinks))
660 cs_links.append(html_tmpl % (uniq_id, morelinks))
662 if len(revs) > 1:
661 if len(revs) > 1:
663 cs_links.append(compare_view)
662 cs_links.append(compare_view)
664 return ''.join(cs_links)
663 return ''.join(cs_links)
665
664
666 def get_fork_name():
665 def get_fork_name():
667 repo_name = action_params
666 repo_name = action_params
668 url_ = url('summary_home', repo_name=repo_name)
667 url_ = url('summary_home', repo_name=repo_name)
669 return _('Fork name %s') % link_to(action_params, url_)
668 return _('Fork name %s') % link_to(action_params, url_)
670
669
671 def get_user_name():
670 def get_user_name():
672 user_name = action_params
671 user_name = action_params
673 return user_name
672 return user_name
674
673
675 def get_users_group():
674 def get_users_group():
676 group_name = action_params
675 group_name = action_params
677 return group_name
676 return group_name
678
677
679 def get_pull_request():
678 def get_pull_request():
680 from kallithea.model.db import PullRequest
679 from kallithea.model.db import PullRequest
681 pull_request_id = action_params
680 pull_request_id = action_params
682 nice_id = PullRequest.make_nice_id(pull_request_id)
681 nice_id = PullRequest.make_nice_id(pull_request_id)
683
682
684 deleted = user_log.repository is None
683 deleted = user_log.repository is None
685 if deleted:
684 if deleted:
686 repo_name = user_log.repository_name
685 repo_name = user_log.repository_name
687 else:
686 else:
688 repo_name = user_log.repository.repo_name
687 repo_name = user_log.repository.repo_name
689
688
690 return link_to(_('Pull request %s') % nice_id,
689 return link_to(_('Pull request %s') % nice_id,
691 url('pullrequest_show', repo_name=repo_name,
690 url('pullrequest_show', repo_name=repo_name,
692 pull_request_id=pull_request_id))
691 pull_request_id=pull_request_id))
693
692
694 def get_archive_name():
693 def get_archive_name():
695 archive_name = action_params
694 archive_name = action_params
696 return archive_name
695 return archive_name
697
696
698 # action : translated str, callback(extractor), icon
697 # action : translated str, callback(extractor), icon
699 action_map = {
698 action_map = {
700 'user_deleted_repo': (_('[deleted] repository'),
699 'user_deleted_repo': (_('[deleted] repository'),
701 None, 'icon-trashcan'),
700 None, 'icon-trashcan'),
702 'user_created_repo': (_('[created] repository'),
701 'user_created_repo': (_('[created] repository'),
703 None, 'icon-plus'),
702 None, 'icon-plus'),
704 'user_created_fork': (_('[created] repository as fork'),
703 'user_created_fork': (_('[created] repository as fork'),
705 None, 'icon-fork'),
704 None, 'icon-fork'),
706 'user_forked_repo': (_('[forked] repository'),
705 'user_forked_repo': (_('[forked] repository'),
707 get_fork_name, 'icon-fork'),
706 get_fork_name, 'icon-fork'),
708 'user_updated_repo': (_('[updated] repository'),
707 'user_updated_repo': (_('[updated] repository'),
709 None, 'icon-pencil'),
708 None, 'icon-pencil'),
710 'user_downloaded_archive': (_('[downloaded] archive from repository'),
709 'user_downloaded_archive': (_('[downloaded] archive from repository'),
711 get_archive_name, 'icon-download-cloud'),
710 get_archive_name, 'icon-download-cloud'),
712 'admin_deleted_repo': (_('[delete] repository'),
711 'admin_deleted_repo': (_('[delete] repository'),
713 None, 'icon-trashcan'),
712 None, 'icon-trashcan'),
714 'admin_created_repo': (_('[created] repository'),
713 'admin_created_repo': (_('[created] repository'),
715 None, 'icon-plus'),
714 None, 'icon-plus'),
716 'admin_forked_repo': (_('[forked] repository'),
715 'admin_forked_repo': (_('[forked] repository'),
717 None, 'icon-fork'),
716 None, 'icon-fork'),
718 'admin_updated_repo': (_('[updated] repository'),
717 'admin_updated_repo': (_('[updated] repository'),
719 None, 'icon-pencil'),
718 None, 'icon-pencil'),
720 'admin_created_user': (_('[created] user'),
719 'admin_created_user': (_('[created] user'),
721 get_user_name, 'icon-user'),
720 get_user_name, 'icon-user'),
722 'admin_updated_user': (_('[updated] user'),
721 'admin_updated_user': (_('[updated] user'),
723 get_user_name, 'icon-user'),
722 get_user_name, 'icon-user'),
724 'admin_created_users_group': (_('[created] user group'),
723 'admin_created_users_group': (_('[created] user group'),
725 get_users_group, 'icon-pencil'),
724 get_users_group, 'icon-pencil'),
726 'admin_updated_users_group': (_('[updated] user group'),
725 'admin_updated_users_group': (_('[updated] user group'),
727 get_users_group, 'icon-pencil'),
726 get_users_group, 'icon-pencil'),
728 'user_commented_revision': (_('[commented] on revision in repository'),
727 'user_commented_revision': (_('[commented] on revision in repository'),
729 get_cs_links, 'icon-comment'),
728 get_cs_links, 'icon-comment'),
730 'user_commented_pull_request': (_('[commented] on pull request for'),
729 'user_commented_pull_request': (_('[commented] on pull request for'),
731 get_pull_request, 'icon-comment'),
730 get_pull_request, 'icon-comment'),
732 'user_closed_pull_request': (_('[closed] pull request for'),
731 'user_closed_pull_request': (_('[closed] pull request for'),
733 get_pull_request, 'icon-ok'),
732 get_pull_request, 'icon-ok'),
734 'push': (_('[pushed] into'),
733 'push': (_('[pushed] into'),
735 get_cs_links, 'icon-move-up'),
734 get_cs_links, 'icon-move-up'),
736 'push_local': (_('[committed via Kallithea] into repository'),
735 'push_local': (_('[committed via Kallithea] into repository'),
737 get_cs_links, 'icon-pencil'),
736 get_cs_links, 'icon-pencil'),
738 'push_remote': (_('[pulled from remote] into repository'),
737 'push_remote': (_('[pulled from remote] into repository'),
739 get_cs_links, 'icon-move-up'),
738 get_cs_links, 'icon-move-up'),
740 'pull': (_('[pulled] from'),
739 'pull': (_('[pulled] from'),
741 None, 'icon-move-down'),
740 None, 'icon-move-down'),
742 'started_following_repo': (_('[started following] repository'),
741 'started_following_repo': (_('[started following] repository'),
743 None, 'icon-heart'),
742 None, 'icon-heart'),
744 'stopped_following_repo': (_('[stopped following] repository'),
743 'stopped_following_repo': (_('[stopped following] repository'),
745 None, 'icon-heart-empty'),
744 None, 'icon-heart-empty'),
746 }
745 }
747
746
748 action_str = action_map.get(action, action)
747 action_str = action_map.get(action, action)
749 if feed:
748 if feed:
750 action = action_str[0].replace('[', '').replace(']', '')
749 action = action_str[0].replace('[', '').replace(']', '')
751 else:
750 else:
752 action = action_str[0] \
751 action = action_str[0] \
753 .replace('[', '<b>') \
752 .replace('[', '<b>') \
754 .replace(']', '</b>')
753 .replace(']', '</b>')
755
754
756 action_params_func = lambda: ""
755 action_params_func = lambda: ""
757
756
758 if callable(action_str[1]):
757 if callable(action_str[1]):
759 action_params_func = action_str[1]
758 action_params_func = action_str[1]
760
759
761 def action_parser_icon():
760 def action_parser_icon():
762 action = user_log.action
761 action = user_log.action
763 action_params = None
762 action_params = None
764 x = action.split(':')
763 x = action.split(':')
765
764
766 if len(x) > 1:
765 if len(x) > 1:
767 action, action_params = x
766 action, action_params = x
768
767
769 ico = action_map.get(action, ['', '', ''])[2]
768 ico = action_map.get(action, ['', '', ''])[2]
770 html = """<i class="%s"></i>""" % ico
769 html = """<i class="%s"></i>""" % ico
771 return literal(html)
770 return literal(html)
772
771
773 # returned callbacks we need to call to get
772 # returned callbacks we need to call to get
774 return [lambda: literal(action), action_params_func, action_parser_icon]
773 return [lambda: literal(action), action_params_func, action_parser_icon]
775
774
776
775
777
776
778 #==============================================================================
777 #==============================================================================
779 # PERMS
778 # PERMS
780 #==============================================================================
779 #==============================================================================
781 from kallithea.lib.auth import HasPermissionAny, \
780 from kallithea.lib.auth import HasPermissionAny, \
782 HasRepoPermissionAny, HasRepoGroupPermissionAny
781 HasRepoPermissionAny, HasRepoGroupPermissionAny
783
782
784
783
785 #==============================================================================
784 #==============================================================================
786 # GRAVATAR URL
785 # GRAVATAR URL
787 #==============================================================================
786 #==============================================================================
788 def gravatar_div(email_address, cls='', size=30, **div_attributes):
787 def gravatar_div(email_address, cls='', size=30, **div_attributes):
789 """Return an html literal with a div around a gravatar if they are enabled.
788 """Return an html literal with a div around a gravatar if they are enabled.
790 Extra keyword parameters starting with 'div_' will get the prefix removed
789 Extra keyword parameters starting with 'div_' will get the prefix removed
791 and '_' changed to '-' and be used as attributes on the div. The default
790 and '_' changed to '-' and be used as attributes on the div. The default
792 class is 'gravatar'.
791 class is 'gravatar'.
793 """
792 """
794 from pylons import tmpl_context as c
793 from pylons import tmpl_context as c
795 if not c.visual.use_gravatar:
794 if not c.visual.use_gravatar:
796 return ''
795 return ''
797 if 'div_class' not in div_attributes:
796 if 'div_class' not in div_attributes:
798 div_attributes['div_class'] = "gravatar"
797 div_attributes['div_class'] = "gravatar"
799 attributes = []
798 attributes = []
800 for k, v in sorted(div_attributes.items()):
799 for k, v in sorted(div_attributes.items()):
801 assert k.startswith('div_'), k
800 assert k.startswith('div_'), k
802 attributes.append(' %s="%s"' % (k[4:].replace('_', '-'), escape(v)))
801 attributes.append(' %s="%s"' % (k[4:].replace('_', '-'), escape(v)))
803 return literal("""<div%s>%s</div>""" %
802 return literal("""<div%s>%s</div>""" %
804 (''.join(attributes),
803 (''.join(attributes),
805 gravatar(email_address, cls=cls, size=size)))
804 gravatar(email_address, cls=cls, size=size)))
806
805
807 def gravatar(email_address, cls='', size=30):
806 def gravatar(email_address, cls='', size=30):
808 """return html element of the gravatar
807 """return html element of the gravatar
809
808
810 This method will return an <img> with the resolution double the size (for
809 This method will return an <img> with the resolution double the size (for
811 retina screens) of the image. If the url returned from gravatar_url is
810 retina screens) of the image. If the url returned from gravatar_url is
812 empty then we fallback to using an icon.
811 empty then we fallback to using an icon.
813
812
814 """
813 """
815 from pylons import tmpl_context as c
814 from pylons import tmpl_context as c
816 if not c.visual.use_gravatar:
815 if not c.visual.use_gravatar:
817 return ''
816 return ''
818
817
819 src = gravatar_url(email_address, size * 2)
818 src = gravatar_url(email_address, size * 2)
820
819
821 if src:
820 if src:
822 # here it makes sense to use style="width: ..." (instead of, say, a
821 # here it makes sense to use style="width: ..." (instead of, say, a
823 # stylesheet) because we using this to generate a high-res (retina) size
822 # stylesheet) because we using this to generate a high-res (retina) size
824 html = ('<img alt="" class="{cls}" style="width: {size}px; height: {size}px" src="{src}"/>'
823 html = ('<img alt="" class="{cls}" style="width: {size}px; height: {size}px" src="{src}"/>'
825 .format(cls=cls, size=size, src=src))
824 .format(cls=cls, size=size, src=src))
826
825
827 else:
826 else:
828 # if src is empty then there was no gravatar, so we use a font icon
827 # if src is empty then there was no gravatar, so we use a font icon
829 html = ("""<i class="icon-user {cls}" style="font-size: {size}px;"></i>"""
828 html = ("""<i class="icon-user {cls}" style="font-size: {size}px;"></i>"""
830 .format(cls=cls, size=size, src=src))
829 .format(cls=cls, size=size, src=src))
831
830
832 return literal(html)
831 return literal(html)
833
832
834 def gravatar_url(email_address, size=30, default=''):
833 def gravatar_url(email_address, size=30, default=''):
835 # doh, we need to re-import those to mock it later
834 # doh, we need to re-import those to mock it later
836 from kallithea.config.routing import url
835 from kallithea.config.routing import url
837 from kallithea.model.db import User
836 from kallithea.model.db import User
838 from pylons import tmpl_context as c
837 from pylons import tmpl_context as c
839 if not c.visual.use_gravatar:
838 if not c.visual.use_gravatar:
840 return ""
839 return ""
841
840
842 _def = 'anonymous@kallithea-scm.org' # default gravatar
841 _def = 'anonymous@kallithea-scm.org' # default gravatar
843 email_address = email_address or _def
842 email_address = email_address or _def
844
843
845 if email_address == _def:
844 if email_address == _def:
846 return default
845 return default
847
846
848 parsed_url = urlparse.urlparse(url.current(qualified=True))
847 parsed_url = urlparse.urlparse(url.current(qualified=True))
849 url = (c.visual.gravatar_url or User.DEFAULT_GRAVATAR_URL ) \
848 url = (c.visual.gravatar_url or User.DEFAULT_GRAVATAR_URL ) \
850 .replace('{email}', email_address) \
849 .replace('{email}', email_address) \
851 .replace('{md5email}', hashlib.md5(safe_str(email_address).lower()).hexdigest()) \
850 .replace('{md5email}', hashlib.md5(safe_str(email_address).lower()).hexdigest()) \
852 .replace('{netloc}', parsed_url.netloc) \
851 .replace('{netloc}', parsed_url.netloc) \
853 .replace('{scheme}', parsed_url.scheme) \
852 .replace('{scheme}', parsed_url.scheme) \
854 .replace('{size}', safe_str(size))
853 .replace('{size}', safe_str(size))
855 return url
854 return url
856
855
857
856
858 def changed_tooltip(nodes):
857 def changed_tooltip(nodes):
859 """
858 """
860 Generates a html string for changed nodes in changeset page.
859 Generates a html string for changed nodes in changeset page.
861 It limits the output to 30 entries
860 It limits the output to 30 entries
862
861
863 :param nodes: LazyNodesGenerator
862 :param nodes: LazyNodesGenerator
864 """
863 """
865 if nodes:
864 if nodes:
866 pref = ': <br/> '
865 pref = ': <br/> '
867 suf = ''
866 suf = ''
868 if len(nodes) > 30:
867 if len(nodes) > 30:
869 suf = '<br/>' + _(' and %s more') % (len(nodes) - 30)
868 suf = '<br/>' + _(' and %s more') % (len(nodes) - 30)
870 return literal(pref + '<br/> '.join([safe_unicode(x.path)
869 return literal(pref + '<br/> '.join([safe_unicode(x.path)
871 for x in nodes[:30]]) + suf)
870 for x in nodes[:30]]) + suf)
872 else:
871 else:
873 return ': ' + _('No files')
872 return ': ' + _('No files')
874
873
875
874
876 def fancy_file_stats(stats):
875 def fancy_file_stats(stats):
877 """
876 """
878 Displays a fancy two colored bar for number of added/deleted
877 Displays a fancy two colored bar for number of added/deleted
879 lines of code on file
878 lines of code on file
880
879
881 :param stats: two element list of added/deleted lines of code
880 :param stats: two element list of added/deleted lines of code
882 """
881 """
883 from kallithea.lib.diffs import NEW_FILENODE, DEL_FILENODE, \
882 from kallithea.lib.diffs import NEW_FILENODE, DEL_FILENODE, \
884 MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE
883 MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE
885
884
886 a, d = stats['added'], stats['deleted']
885 a, d = stats['added'], stats['deleted']
887 width = 100
886 width = 100
888
887
889 if stats['binary']:
888 if stats['binary']:
890 #binary mode
889 #binary mode
891 lbl = ''
890 lbl = ''
892 bin_op = 1
891 bin_op = 1
893
892
894 if BIN_FILENODE in stats['ops']:
893 if BIN_FILENODE in stats['ops']:
895 lbl = 'bin+'
894 lbl = 'bin+'
896
895
897 if NEW_FILENODE in stats['ops']:
896 if NEW_FILENODE in stats['ops']:
898 lbl += _('new file')
897 lbl += _('new file')
899 bin_op = NEW_FILENODE
898 bin_op = NEW_FILENODE
900 elif MOD_FILENODE in stats['ops']:
899 elif MOD_FILENODE in stats['ops']:
901 lbl += _('mod')
900 lbl += _('mod')
902 bin_op = MOD_FILENODE
901 bin_op = MOD_FILENODE
903 elif DEL_FILENODE in stats['ops']:
902 elif DEL_FILENODE in stats['ops']:
904 lbl += _('del')
903 lbl += _('del')
905 bin_op = DEL_FILENODE
904 bin_op = DEL_FILENODE
906 elif RENAMED_FILENODE in stats['ops']:
905 elif RENAMED_FILENODE in stats['ops']:
907 lbl += _('rename')
906 lbl += _('rename')
908 bin_op = RENAMED_FILENODE
907 bin_op = RENAMED_FILENODE
909
908
910 #chmod can go with other operations
909 #chmod can go with other operations
911 if CHMOD_FILENODE in stats['ops']:
910 if CHMOD_FILENODE in stats['ops']:
912 _org_lbl = _('chmod')
911 _org_lbl = _('chmod')
913 lbl += _org_lbl if lbl.endswith('+') else '+%s' % _org_lbl
912 lbl += _org_lbl if lbl.endswith('+') else '+%s' % _org_lbl
914
913
915 #import ipdb;ipdb.set_trace()
914 #import ipdb;ipdb.set_trace()
916 b_d = '<div class="bin bin%s progress-bar" style="width:100%%">%s</div>' % (bin_op, lbl)
915 b_d = '<div class="bin bin%s progress-bar" style="width:100%%">%s</div>' % (bin_op, lbl)
917 b_a = '<div class="bin bin1" style="width:0%"></div>'
916 b_a = '<div class="bin bin1" style="width:0%"></div>'
918 return literal('<div style="width:%spx" class="progress">%s%s</div>' % (width, b_a, b_d))
917 return literal('<div style="width:%spx" class="progress">%s%s</div>' % (width, b_a, b_d))
919
918
920 t = stats['added'] + stats['deleted']
919 t = stats['added'] + stats['deleted']
921 unit = float(width) / (t or 1)
920 unit = float(width) / (t or 1)
922
921
923 # needs > 9% of width to be visible or 0 to be hidden
922 # needs > 9% of width to be visible or 0 to be hidden
924 a_p = max(9, unit * a) if a > 0 else 0
923 a_p = max(9, unit * a) if a > 0 else 0
925 d_p = max(9, unit * d) if d > 0 else 0
924 d_p = max(9, unit * d) if d > 0 else 0
926 p_sum = a_p + d_p
925 p_sum = a_p + d_p
927
926
928 if p_sum > width:
927 if p_sum > width:
929 #adjust the percentage to be == 100% since we adjusted to 9
928 #adjust the percentage to be == 100% since we adjusted to 9
930 if a_p > d_p:
929 if a_p > d_p:
931 a_p = a_p - (p_sum - width)
930 a_p = a_p - (p_sum - width)
932 else:
931 else:
933 d_p = d_p - (p_sum - width)
932 d_p = d_p - (p_sum - width)
934
933
935 a_v = a if a > 0 else ''
934 a_v = a if a > 0 else ''
936 d_v = d if d > 0 else ''
935 d_v = d if d > 0 else ''
937
936
938 d_a = '<div class="added progress-bar" style="width:%s%%">%s</div>' % (
937 d_a = '<div class="added progress-bar" style="width:%s%%">%s</div>' % (
939 a_p, a_v
938 a_p, a_v
940 )
939 )
941 d_d = '<div class="deleted progress-bar" style="width:%s%%">%s</div>' % (
940 d_d = '<div class="deleted progress-bar" style="width:%s%%">%s</div>' % (
942 d_p, d_v
941 d_p, d_v
943 )
942 )
944 return literal('<div class="pull-right progress" style="width:%spx">%s%s</div>' % (width, d_a, d_d))
943 return literal('<div class="pull-right progress" style="width:%spx">%s%s</div>' % (width, d_a, d_d))
945
944
946
945
947 _URLIFY_RE = re.compile(r'''
946 _URLIFY_RE = re.compile(r'''
948 # URL markup
947 # URL markup
949 (?P<url>%s) |
948 (?P<url>%s) |
950 # @mention markup
949 # @mention markup
951 (?P<mention>%s) |
950 (?P<mention>%s) |
952 # Changeset hash markup
951 # Changeset hash markup
953 (?<!\w|[-_])
952 (?<!\w|[-_])
954 (?P<hash>[0-9a-f]{12,40})
953 (?P<hash>[0-9a-f]{12,40})
955 (?!\w|[-_]) |
954 (?!\w|[-_]) |
956 # Markup of *bold text*
955 # Markup of *bold text*
957 (?:
956 (?:
958 (?:^|(?<=\s))
957 (?:^|(?<=\s))
959 (?P<bold> [*] (?!\s) [^*\n]* (?<!\s) [*] )
958 (?P<bold> [*] (?!\s) [^*\n]* (?<!\s) [*] )
960 (?![*\w])
959 (?![*\w])
961 ) |
960 ) |
962 # "Stylize" markup
961 # "Stylize" markup
963 \[see\ \=&gt;\ *(?P<seen>[a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\] |
962 \[see\ \=&gt;\ *(?P<seen>[a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\] |
964 \[license\ \=&gt;\ *(?P<license>[a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\] |
963 \[license\ \=&gt;\ *(?P<license>[a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\] |
965 \[(?P<tagtype>requires|recommends|conflicts|base)\ \=&gt;\ *(?P<tagvalue>[a-zA-Z0-9\-\/]*)\] |
964 \[(?P<tagtype>requires|recommends|conflicts|base)\ \=&gt;\ *(?P<tagvalue>[a-zA-Z0-9\-\/]*)\] |
966 \[(?:lang|language)\ \=&gt;\ *(?P<lang>[a-zA-Z\-\/\#\+]*)\] |
965 \[(?:lang|language)\ \=&gt;\ *(?P<lang>[a-zA-Z\-\/\#\+]*)\] |
967 \[(?P<tag>[a-z]+)\]
966 \[(?P<tag>[a-z]+)\]
968 ''' % (url_re.pattern, MENTIONS_REGEX.pattern),
967 ''' % (url_re.pattern, MENTIONS_REGEX.pattern),
969 re.VERBOSE | re.MULTILINE | re.IGNORECASE)
968 re.VERBOSE | re.MULTILINE | re.IGNORECASE)
970
969
971
970
972
971
973 def urlify_text(s, repo_name=None, link_=None, truncate=None, stylize=False, truncatef=truncate):
972 def urlify_text(s, repo_name=None, link_=None, truncate=None, stylize=False, truncatef=truncate):
974 """
973 """
975 Parses given text message and make literal html with markup.
974 Parses given text message and make literal html with markup.
976 The text will be truncated to the specified length.
975 The text will be truncated to the specified length.
977 Hashes are turned into changeset links to specified repository.
976 Hashes are turned into changeset links to specified repository.
978 URLs links to what they say.
977 URLs links to what they say.
979 Issues are linked to given issue-server.
978 Issues are linked to given issue-server.
980 If link_ is provided, all text not already linking somewhere will link there.
979 If link_ is provided, all text not already linking somewhere will link there.
981 """
980 """
982
981
983 def _replace(match_obj):
982 def _replace(match_obj):
984 url = match_obj.group('url')
983 url = match_obj.group('url')
985 if url is not None:
984 if url is not None:
986 return '<a href="%(url)s">%(url)s</a>' % {'url': url}
985 return '<a href="%(url)s">%(url)s</a>' % {'url': url}
987 mention = match_obj.group('mention')
986 mention = match_obj.group('mention')
988 if mention is not None:
987 if mention is not None:
989 return '<b>%s</b>' % mention
988 return '<b>%s</b>' % mention
990 hash_ = match_obj.group('hash')
989 hash_ = match_obj.group('hash')
991 if hash_ is not None and repo_name is not None:
990 if hash_ is not None and repo_name is not None:
992 from kallithea.config.routing import url # doh, we need to re-import url to mock it later
991 from kallithea.config.routing import url # doh, we need to re-import url to mock it later
993 return '<a class="revision-link" href="%(url)s">%(hash)s</a>' % {
992 return '<a class="revision-link" href="%(url)s">%(hash)s</a>' % {
994 'url': url('changeset_home', repo_name=repo_name, revision=hash_),
993 'url': url('changeset_home', repo_name=repo_name, revision=hash_),
995 'hash': hash_,
994 'hash': hash_,
996 }
995 }
997 bold = match_obj.group('bold')
996 bold = match_obj.group('bold')
998 if bold is not None:
997 if bold is not None:
999 return '<b>*%s*</b>' % _urlify(bold[1:-1])
998 return '<b>*%s*</b>' % _urlify(bold[1:-1])
1000 if stylize:
999 if stylize:
1001 seen = match_obj.group('seen')
1000 seen = match_obj.group('seen')
1002 if seen:
1001 if seen:
1003 return '<div class="metatag" data-tag="see">see =&gt; %s</div>' % seen
1002 return '<div class="metatag" data-tag="see">see =&gt; %s</div>' % seen
1004 license = match_obj.group('license')
1003 license = match_obj.group('license')
1005 if license:
1004 if license:
1006 return '<div class="metatag" data-tag="license"><a href="http:\/\/www.opensource.org/licenses/%s">%s</a></div>' % (license, license)
1005 return '<div class="metatag" data-tag="license"><a href="http:\/\/www.opensource.org/licenses/%s">%s</a></div>' % (license, license)
1007 tagtype = match_obj.group('tagtype')
1006 tagtype = match_obj.group('tagtype')
1008 if tagtype:
1007 if tagtype:
1009 tagvalue = match_obj.group('tagvalue')
1008 tagvalue = match_obj.group('tagvalue')
1010 return '<div class="metatag" data-tag="%s">%s =&gt; <a href="/%s">%s</a></div>' % (tagtype, tagtype, tagvalue, tagvalue)
1009 return '<div class="metatag" data-tag="%s">%s =&gt; <a href="/%s">%s</a></div>' % (tagtype, tagtype, tagvalue, tagvalue)
1011 lang = match_obj.group('lang')
1010 lang = match_obj.group('lang')
1012 if lang:
1011 if lang:
1013 return '<div class="metatag" data-tag="lang">%s</div>' % lang
1012 return '<div class="metatag" data-tag="lang">%s</div>' % lang
1014 tag = match_obj.group('tag')
1013 tag = match_obj.group('tag')
1015 if tag:
1014 if tag:
1016 return '<div class="metatag" data-tag="%s">%s</div>' % (tag, tag)
1015 return '<div class="metatag" data-tag="%s">%s</div>' % (tag, tag)
1017 return match_obj.group(0)
1016 return match_obj.group(0)
1018
1017
1019 def _urlify(s):
1018 def _urlify(s):
1020 """
1019 """
1021 Extract urls from text and make html links out of them
1020 Extract urls from text and make html links out of them
1022 """
1021 """
1023 return _URLIFY_RE.sub(_replace, s)
1022 return _URLIFY_RE.sub(_replace, s)
1024
1023
1025 if truncate is None:
1024 if truncate is None:
1026 s = s.rstrip()
1025 s = s.rstrip()
1027 else:
1026 else:
1028 s = truncatef(s, truncate, whole_word=True)
1027 s = truncatef(s, truncate, whole_word=True)
1029 s = html_escape(s)
1028 s = html_escape(s)
1030 s = _urlify(s)
1029 s = _urlify(s)
1031 if repo_name is not None:
1030 if repo_name is not None:
1032 s = urlify_issues(s, repo_name)
1031 s = urlify_issues(s, repo_name)
1033 if link_ is not None:
1032 if link_ is not None:
1034 # make href around everything that isn't a href already
1033 # make href around everything that isn't a href already
1035 s = linkify_others(s, link_)
1034 s = linkify_others(s, link_)
1036 s = s.replace('\r\n', '<br/>').replace('\n', '<br/>')
1035 s = s.replace('\r\n', '<br/>').replace('\n', '<br/>')
1037 return literal(s)
1036 return literal(s)
1038
1037
1039
1038
1040 def linkify_others(t, l):
1039 def linkify_others(t, l):
1041 """Add a default link to html with links.
1040 """Add a default link to html with links.
1042 HTML doesn't allow nesting of links, so the outer link must be broken up
1041 HTML doesn't allow nesting of links, so the outer link must be broken up
1043 in pieces and give space for other links.
1042 in pieces and give space for other links.
1044 """
1043 """
1045 urls = re.compile(r'(\<a.*?\<\/a\>)',)
1044 urls = re.compile(r'(\<a.*?\<\/a\>)',)
1046 links = []
1045 links = []
1047 for e in urls.split(t):
1046 for e in urls.split(t):
1048 if e.strip() and not urls.match(e):
1047 if e.strip() and not urls.match(e):
1049 links.append('<a class="message-link" href="%s">%s</a>' % (l, e))
1048 links.append('<a class="message-link" href="%s">%s</a>' % (l, e))
1050 else:
1049 else:
1051 links.append(e)
1050 links.append(e)
1052
1051
1053 return ''.join(links)
1052 return ''.join(links)
1054
1053
1055
1054
1056 # Global variable that will hold the actual urlify_issues function body.
1055 # Global variable that will hold the actual urlify_issues function body.
1057 # Will be set on first use when the global configuration has been read.
1056 # Will be set on first use when the global configuration has been read.
1058 _urlify_issues_f = None
1057 _urlify_issues_f = None
1059
1058
1060
1059
1061 def urlify_issues(newtext, repo_name):
1060 def urlify_issues(newtext, repo_name):
1062 """Urlify issue references according to .ini configuration"""
1061 """Urlify issue references according to .ini configuration"""
1063 global _urlify_issues_f
1062 global _urlify_issues_f
1064 if _urlify_issues_f is None:
1063 if _urlify_issues_f is None:
1065 from kallithea import CONFIG
1064 from kallithea import CONFIG
1066 from kallithea.model.db import URL_SEP
1065 from kallithea.model.db import URL_SEP
1067 assert CONFIG['sqlalchemy.url'] # make sure config has been loaded
1066 assert CONFIG['sqlalchemy.url'] # make sure config has been loaded
1068
1067
1069 # Build chain of urlify functions, starting with not doing any transformation
1068 # Build chain of urlify functions, starting with not doing any transformation
1070 tmp_urlify_issues_f = lambda s: s
1069 tmp_urlify_issues_f = lambda s: s
1071
1070
1072 issue_pat_re = re.compile(r'issue_pat(.*)')
1071 issue_pat_re = re.compile(r'issue_pat(.*)')
1073 for k in CONFIG.keys():
1072 for k in CONFIG.keys():
1074 # Find all issue_pat* settings that also have corresponding server_link and prefix configuration
1073 # Find all issue_pat* settings that also have corresponding server_link and prefix configuration
1075 m = issue_pat_re.match(k)
1074 m = issue_pat_re.match(k)
1076 if m is None:
1075 if m is None:
1077 continue
1076 continue
1078 suffix = m.group(1)
1077 suffix = m.group(1)
1079 issue_pat = CONFIG.get(k)
1078 issue_pat = CONFIG.get(k)
1080 issue_server_link = CONFIG.get('issue_server_link%s' % suffix)
1079 issue_server_link = CONFIG.get('issue_server_link%s' % suffix)
1081 issue_prefix = CONFIG.get('issue_prefix%s' % suffix)
1080 issue_prefix = CONFIG.get('issue_prefix%s' % suffix)
1082 if issue_pat and issue_server_link and issue_prefix:
1081 if issue_pat and issue_server_link and issue_prefix:
1083 log.debug('issue pattern %r: %r -> %r %r', suffix, issue_pat, issue_server_link, issue_prefix)
1082 log.debug('issue pattern %r: %r -> %r %r', suffix, issue_pat, issue_server_link, issue_prefix)
1084 else:
1083 else:
1085 log.error('skipping incomplete issue pattern %r: %r -> %r %r', suffix, issue_pat, issue_server_link, issue_prefix)
1084 log.error('skipping incomplete issue pattern %r: %r -> %r %r', suffix, issue_pat, issue_server_link, issue_prefix)
1086 continue
1085 continue
1087
1086
1088 # Wrap tmp_urlify_issues_f with substitution of this pattern, while making sure all loop variables (and compiled regexpes) are bound
1087 # Wrap tmp_urlify_issues_f with substitution of this pattern, while making sure all loop variables (and compiled regexpes) are bound
1089 issue_re = re.compile(issue_pat)
1088 issue_re = re.compile(issue_pat)
1090 def issues_replace(match_obj,
1089 def issues_replace(match_obj,
1091 issue_server_link=issue_server_link, issue_prefix=issue_prefix):
1090 issue_server_link=issue_server_link, issue_prefix=issue_prefix):
1092 leadingspace = ' ' if match_obj.group().startswith(' ') else ''
1091 leadingspace = ' ' if match_obj.group().startswith(' ') else ''
1093 issue_id = ''.join(match_obj.groups())
1092 issue_id = ''.join(match_obj.groups())
1094 issue_url = issue_server_link.replace('{id}', issue_id)
1093 issue_url = issue_server_link.replace('{id}', issue_id)
1095 issue_url = issue_url.replace('{repo}', repo_name)
1094 issue_url = issue_url.replace('{repo}', repo_name)
1096 issue_url = issue_url.replace('{repo_name}', repo_name.split(URL_SEP)[-1])
1095 issue_url = issue_url.replace('{repo_name}', repo_name.split(URL_SEP)[-1])
1097 return (
1096 return (
1098 '%(leadingspace)s<a class="issue-tracker-link" href="%(url)s">'
1097 '%(leadingspace)s<a class="issue-tracker-link" href="%(url)s">'
1099 '%(issue-prefix)s%(id-repr)s'
1098 '%(issue-prefix)s%(id-repr)s'
1100 '</a>'
1099 '</a>'
1101 ) % {
1100 ) % {
1102 'leadingspace': leadingspace,
1101 'leadingspace': leadingspace,
1103 'url': issue_url,
1102 'url': issue_url,
1104 'id-repr': issue_id,
1103 'id-repr': issue_id,
1105 'issue-prefix': issue_prefix,
1104 'issue-prefix': issue_prefix,
1106 'serv': issue_server_link,
1105 'serv': issue_server_link,
1107 }
1106 }
1108 tmp_urlify_issues_f = (lambda s,
1107 tmp_urlify_issues_f = (lambda s,
1109 issue_re=issue_re, issues_replace=issues_replace, chain_f=tmp_urlify_issues_f:
1108 issue_re=issue_re, issues_replace=issues_replace, chain_f=tmp_urlify_issues_f:
1110 issue_re.sub(issues_replace, chain_f(s)))
1109 issue_re.sub(issues_replace, chain_f(s)))
1111
1110
1112 # Set tmp function globally - atomically
1111 # Set tmp function globally - atomically
1113 _urlify_issues_f = tmp_urlify_issues_f
1112 _urlify_issues_f = tmp_urlify_issues_f
1114
1113
1115 return _urlify_issues_f(newtext)
1114 return _urlify_issues_f(newtext)
1116
1115
1117
1116
1118 def render_w_mentions(source, repo_name=None):
1117 def render_w_mentions(source, repo_name=None):
1119 """
1118 """
1120 Render plain text with revision hashes and issue references urlified
1119 Render plain text with revision hashes and issue references urlified
1121 and with @mention highlighting.
1120 and with @mention highlighting.
1122 """
1121 """
1123 s = safe_unicode(source)
1122 s = safe_unicode(source)
1124 s = urlify_text(s, repo_name=repo_name)
1123 s = urlify_text(s, repo_name=repo_name)
1125 return literal('<div class="formatted-fixed">%s</div>' % s)
1124 return literal('<div class="formatted-fixed">%s</div>' % s)
1126
1125
1127
1126
1128 def short_ref(ref_type, ref_name):
1127 def short_ref(ref_type, ref_name):
1129 if ref_type == 'rev':
1128 if ref_type == 'rev':
1130 return short_id(ref_name)
1129 return short_id(ref_name)
1131 return ref_name
1130 return ref_name
1132
1131
1133 def link_to_ref(repo_name, ref_type, ref_name, rev=None):
1132 def link_to_ref(repo_name, ref_type, ref_name, rev=None):
1134 """
1133 """
1135 Return full markup for a href to changeset_home for a changeset.
1134 Return full markup for a href to changeset_home for a changeset.
1136 If ref_type is branch it will link to changelog.
1135 If ref_type is branch it will link to changelog.
1137 ref_name is shortened if ref_type is 'rev'.
1136 ref_name is shortened if ref_type is 'rev'.
1138 if rev is specified show it too, explicitly linking to that revision.
1137 if rev is specified show it too, explicitly linking to that revision.
1139 """
1138 """
1140 txt = short_ref(ref_type, ref_name)
1139 txt = short_ref(ref_type, ref_name)
1141 if ref_type == 'branch':
1140 if ref_type == 'branch':
1142 u = url('changelog_home', repo_name=repo_name, branch=ref_name)
1141 u = url('changelog_home', repo_name=repo_name, branch=ref_name)
1143 else:
1142 else:
1144 u = url('changeset_home', repo_name=repo_name, revision=ref_name)
1143 u = url('changeset_home', repo_name=repo_name, revision=ref_name)
1145 l = link_to(repo_name + '#' + txt, u)
1144 l = link_to(repo_name + '#' + txt, u)
1146 if rev and ref_type != 'rev':
1145 if rev and ref_type != 'rev':
1147 l = literal('%s (%s)' % (l, link_to(short_id(rev), url('changeset_home', repo_name=repo_name, revision=rev))))
1146 l = literal('%s (%s)' % (l, link_to(short_id(rev), url('changeset_home', repo_name=repo_name, revision=rev))))
1148 return l
1147 return l
1149
1148
1150 def changeset_status(repo, revision):
1149 def changeset_status(repo, revision):
1151 from kallithea.model.changeset_status import ChangesetStatusModel
1150 from kallithea.model.changeset_status import ChangesetStatusModel
1152 return ChangesetStatusModel().get_status(repo, revision)
1151 return ChangesetStatusModel().get_status(repo, revision)
1153
1152
1154
1153
1155 def changeset_status_lbl(changeset_status):
1154 def changeset_status_lbl(changeset_status):
1156 from kallithea.model.db import ChangesetStatus
1155 from kallithea.model.db import ChangesetStatus
1157 return ChangesetStatus.get_status_lbl(changeset_status)
1156 return ChangesetStatus.get_status_lbl(changeset_status)
1158
1157
1159
1158
1160 def get_permission_name(key):
1159 def get_permission_name(key):
1161 from kallithea.model.db import Permission
1160 from kallithea.model.db import Permission
1162 return dict(Permission.PERMS).get(key)
1161 return dict(Permission.PERMS).get(key)
1163
1162
1164
1163
1165 def journal_filter_help():
1164 def journal_filter_help():
1166 return _(textwrap.dedent('''
1165 return _(textwrap.dedent('''
1167 Example filter terms:
1166 Example filter terms:
1168 repository:vcs
1167 repository:vcs
1169 username:developer
1168 username:developer
1170 action:*push*
1169 action:*push*
1171 ip:127.0.0.1
1170 ip:127.0.0.1
1172 date:20120101
1171 date:20120101
1173 date:[20120101100000 TO 20120102]
1172 date:[20120101100000 TO 20120102]
1174
1173
1175 Generate wildcards using '*' character:
1174 Generate wildcards using '*' character:
1176 "repository:vcs*" - search everything starting with 'vcs'
1175 "repository:vcs*" - search everything starting with 'vcs'
1177 "repository:*vcs*" - search for repository containing 'vcs'
1176 "repository:*vcs*" - search for repository containing 'vcs'
1178
1177
1179 Optional AND / OR operators in queries
1178 Optional AND / OR operators in queries
1180 "repository:vcs OR repository:test"
1179 "repository:vcs OR repository:test"
1181 "username:test AND repository:test*"
1180 "username:test AND repository:test*"
1182 '''))
1181 '''))
1183
1182
1184
1183
1185 def not_mapped_error(repo_name):
1184 def not_mapped_error(repo_name):
1186 flash(_('%s repository is not mapped to db perhaps'
1185 flash(_('%s repository is not mapped to db perhaps'
1187 ' it was created or renamed from the filesystem'
1186 ' it was created or renamed from the filesystem'
1188 ' please run the application again'
1187 ' please run the application again'
1189 ' in order to rescan repositories') % repo_name, category='error')
1188 ' in order to rescan repositories') % repo_name, category='error')
1190
1189
1191
1190
1192 def ip_range(ip_addr):
1191 def ip_range(ip_addr):
1193 from kallithea.model.db import UserIpMap
1192 from kallithea.model.db import UserIpMap
1194 s, e = UserIpMap._get_ip_range(ip_addr)
1193 s, e = UserIpMap._get_ip_range(ip_addr)
1195 return '%s - %s' % (s, e)
1194 return '%s - %s' % (s, e)
1196
1195
1197
1196
1198 def form(url, method="post", **attrs):
1197 def form(url, method="post", **attrs):
1199 """Like webhelpers.html.tags.form but automatically using secure_form with
1198 """Like webhelpers.html.tags.form but automatically using secure_form with
1200 authentication_token for POST. authentication_token is thus never leaked
1199 authentication_token for POST. authentication_token is thus never leaked
1201 in the URL."""
1200 in the URL."""
1202 if method.lower() == 'get':
1201 if method.lower() == 'get':
1203 return insecure_form(url, method=method, **attrs)
1202 return insecure_form(url, method=method, **attrs)
1204 # webhelpers will turn everything but GET into POST
1203 # webhelpers will turn everything but GET into POST
1205 return secure_form(url, method=method, **attrs)
1204 return secure_form(url, method=method, **attrs)
@@ -1,4436 +1,4546 b''
1 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td {
1 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td {
2 border: 0;
2 border: 0;
3 outline: 0;
3 outline: 0;
4 font-size: 100%;
4 font-size: 100%;
5 vertical-align: baseline;
5 vertical-align: baseline;
6 background: transparent;
6 background: transparent;
7 margin: 0;
7 margin: 0;
8 padding: 0;
8 padding: 0;
9 }
9 }
10
10
11 body {
11 body {
12 line-height: 1;
12 line-height: 1;
13 height: 100%;
13 height: 100%;
14 background: url("../images/background.png") repeat scroll 0 0 #B0B0B0;
14 background: url("../images/background.png") repeat scroll 0 0 #B0B0B0;
15 font-family: Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
15 font-family: Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
16 color: #000;
16 color: #000;
17 margin: 0;
17 margin: 0;
18 padding: 0;
18 padding: 0;
19 font-size: 12px;
19 font-size: 12px;
20 }
20 }
21
21
22 ol, ul {
22 ol, ul {
23 list-style: none;
23 list-style: none;
24 }
24 }
25
25
26 blockquote, q {
26 blockquote, q {
27 quotes: none;
27 quotes: none;
28 }
28 }
29
29
30 blockquote:before, blockquote:after, q:before, q:after {
30 blockquote:before, blockquote:after, q:before, q:after {
31 content: none;
31 content: none;
32 }
32 }
33
33
34 :focus {
34 :focus {
35 outline: 0;
35 outline: 0;
36 }
36 }
37
37
38 del {
38 del {
39 text-decoration: line-through;
39 text-decoration: line-through;
40 }
40 }
41
41
42 table {
42 table {
43 border-collapse: collapse;
43 border-collapse: collapse;
44 border-spacing: 0;
44 border-spacing: 0;
45 }
45 }
46
46
47 html {
47 html {
48 height: 100%;
48 height: 100%;
49 }
49 }
50
50
51 a {
51 a {
52 color: #577632;
52 color: #577632;
53 text-decoration: none;
53 text-decoration: none;
54 cursor: pointer;
54 cursor: pointer;
55 }
55 }
56
56
57 a:hover {
57 a:hover {
58 color: #576622;
58 color: #576622;
59 text-decoration: underline;
59 text-decoration: underline;
60 }
60 }
61
61
62 h1, h2, h3, h4, h5, h6,
62 h1, h2, h3, h4, h5, h6,
63 div.h1, div.h2, div.h3, div.h4, div.h5, div.h6 {
63 div.h1, div.h2, div.h3, div.h4, div.h5, div.h6 {
64 color: #292929;
64 color: #292929;
65 font-weight: 700;
65 font-weight: 700;
66 }
66 }
67
67
68 h1, div.h1 {
68 h1, div.h1 {
69 font-size: 22px;
69 font-size: 22px;
70 }
70 }
71
71
72 h2, div.h2 {
72 h2, div.h2 {
73 font-size: 20px;
73 font-size: 20px;
74 }
74 }
75
75
76 h3, div.h3 {
76 h3, div.h3 {
77 font-size: 18px;
77 font-size: 18px;
78 }
78 }
79
79
80 h4, div.h4 {
80 h4, div.h4 {
81 font-size: 16px;
81 font-size: 16px;
82 }
82 }
83
83
84 h5, div.h5 {
84 h5, div.h5 {
85 font-size: 14px;
85 font-size: 14px;
86 }
86 }
87
87
88 h6, div.h6 {
88 h6, div.h6 {
89 font-size: 11px;
89 font-size: 11px;
90 }
90 }
91
91
92 ul.circle {
92 ul.circle {
93 list-style-type: circle;
93 list-style-type: circle;
94 }
94 }
95
95
96 ul.disc {
96 ul.disc {
97 list-style-type: disc;
97 list-style-type: disc;
98 }
98 }
99
99
100 ul.square {
100 ul.square {
101 list-style-type: square;
101 list-style-type: square;
102 }
102 }
103
103
104 ol.lower-roman {
104 ol.lower-roman {
105 list-style-type: lower-roman;
105 list-style-type: lower-roman;
106 }
106 }
107
107
108 ol.upper-roman {
108 ol.upper-roman {
109 list-style-type: upper-roman;
109 list-style-type: upper-roman;
110 }
110 }
111
111
112 ol.lower-alpha {
112 ol.lower-alpha {
113 list-style-type: lower-alpha;
113 list-style-type: lower-alpha;
114 }
114 }
115
115
116 ol.upper-alpha {
116 ol.upper-alpha {
117 list-style-type: upper-alpha;
117 list-style-type: upper-alpha;
118 }
118 }
119
119
120 ol.decimal {
120 ol.decimal {
121 list-style-type: decimal;
121 list-style-type: decimal;
122 }
122 }
123
123
124 div.color {
124 div.color {
125 clear: both;
125 clear: both;
126 overflow: hidden;
126 overflow: hidden;
127 position: absolute;
127 position: absolute;
128 background: #FFF;
128 background: #FFF;
129 margin: 7px 0 0 60px;
129 margin: 7px 0 0 60px;
130 padding: 1px 1px 1px 0;
130 padding: 1px 1px 1px 0;
131 }
131 }
132
132
133 div.color a {
133 div.color a {
134 width: 15px;
134 width: 15px;
135 height: 15px;
135 height: 15px;
136 display: block;
136 display: block;
137 float: left;
137 float: left;
138 margin: 0 0 0 1px;
138 margin: 0 0 0 1px;
139 padding: 0;
139 padding: 0;
140 }
140 }
141
141
142 div.options {
142 div.options {
143 clear: both;
143 clear: both;
144 overflow: hidden;
144 overflow: hidden;
145 position: absolute;
145 position: absolute;
146 background: #FFF;
146 background: #FFF;
147 margin: 7px 0 0 162px;
147 margin: 7px 0 0 162px;
148 padding: 0;
148 padding: 0;
149 }
149 }
150
150
151 div.options a {
151 div.options a {
152 height: 1%;
152 height: 1%;
153 display: block;
153 display: block;
154 text-decoration: none;
154 text-decoration: none;
155 margin: 0;
155 margin: 0;
156 padding: 3px 8px;
156 padding: 3px 8px;
157 }
157 }
158
158
159 code,
159 code,
160 .code pre,
160 .code pre,
161 div.readme .readme_box pre,
161 div.readme .readme_box pre,
162 div.rst-block pre,
162 div.rst-block pre,
163 div.formatted-fixed,
163 div.formatted-fixed,
164 #changeset_content div.message,
164 #changeset_content div.message,
165 .CodeMirror .CodeMirror-code pre {
165 .CodeMirror .CodeMirror-code pre {
166 font-size: 12px;
166 font-size: 12px;
167 font-family: Lucida Console, Consolas, Monaco, Inconsolata, Liberation Mono, monospace;
167 font-family: Lucida Console, Consolas, Monaco, Inconsolata, Liberation Mono, monospace;
168 }
168 }
169
169
170 div.formatted-fixed {
170 div.formatted-fixed {
171 white-space: pre-wrap;
171 white-space: pre-wrap;
172 }
172 }
173
173
174 .changeset_hash {
174 .changeset_hash {
175 font-family: Lucida Console, Consolas, Monaco, Inconsolata, Liberation Mono, monospace;
175 font-family: Lucida Console, Consolas, Monaco, Inconsolata, Liberation Mono, monospace;
176 }
176 }
177
177
178 .top-left-rounded-corner {
178 .top-left-rounded-corner {
179 border-top-left-radius: 8px;
179 border-top-left-radius: 8px;
180 }
180 }
181
181
182 .top-right-rounded-corner {
182 .top-right-rounded-corner {
183 border-top-right-radius: 8px;
183 border-top-right-radius: 8px;
184 }
184 }
185
185
186 .bottom-left-rounded-corner {
186 .bottom-left-rounded-corner {
187 border-bottom-left-radius: 8px;
187 border-bottom-left-radius: 8px;
188 }
188 }
189
189
190 .bottom-right-rounded-corner {
190 .bottom-right-rounded-corner {
191 border-bottom-right-radius: 8px;
191 border-bottom-right-radius: 8px;
192 }
192 }
193
193
194 .top-left-rounded-corner-mid {
194 .top-left-rounded-corner-mid {
195 border-top-left-radius: 4px;
195 border-top-left-radius: 4px;
196 }
196 }
197
197
198 .top-right-rounded-corner-mid {
198 .top-right-rounded-corner-mid {
199 border-top-right-radius: 4px;
199 border-top-right-radius: 4px;
200 }
200 }
201
201
202 .bottom-left-rounded-corner-mid {
202 .bottom-left-rounded-corner-mid {
203 border-bottom-left-radius: 4px;
203 border-bottom-left-radius: 4px;
204 }
204 }
205
205
206 .bottom-right-rounded-corner-mid {
206 .bottom-right-rounded-corner-mid {
207 border-bottom-right-radius: 4px;
207 border-bottom-right-radius: 4px;
208 }
208 }
209
209
210 .help-block {
210 .help-block {
211 color: #999999;
211 color: #999999;
212 display: block;
212 display: block;
213 margin: 0 0 10px;
213 margin: 0 0 10px;
214 }
214 }
215
215
216 .empty_data {
216 .empty_data {
217 color: #B9B9B9;
217 color: #B9B9B9;
218 }
218 }
219
219
220 .inline-comments-general.show-general-status .hidden.general-only {
220 .inline-comments-general.show-general-status .hidden.general-only {
221 display: block !important;
221 display: block !important;
222 }
222 }
223
223
224 /* Bootstrap compatible */
224 /* Bootstrap compatible */
225 .show {
225 .show {
226 display: block !important;
226 display: block !important;
227 }
227 }
228 .hidden {
228 .hidden {
229 display: none !important;
229 display: none !important;
230 }
230 }
231 .invisible {
231 .invisible {
232 visibility: hidden;
232 visibility: hidden;
233 }
233 }
234
234
235 .truncate {
235 .truncate {
236 white-space: nowrap;
236 white-space: nowrap;
237 overflow: hidden;
237 overflow: hidden;
238 text-overflow: ellipsis;
238 text-overflow: ellipsis;
239 -o-text-overflow: ellipsis;
239 -o-text-overflow: ellipsis;
240 -ms-text-overflow: ellipsis;
240 -ms-text-overflow: ellipsis;
241 }
241 }
242
242
243 .truncate.autoexpand:hover {
243 .truncate.autoexpand:hover {
244 overflow: visible;
244 overflow: visible;
245 }
245 }
246
246
247 a.permalink {
247 a.permalink {
248 visibility: hidden;
248 visibility: hidden;
249 position: absolute;
249 position: absolute;
250 margin: 3px 4px;
250 margin: 3px 4px;
251 }
251 }
252
252
253 a.permalink:hover {
253 a.permalink:hover {
254 text-decoration: none;
254 text-decoration: none;
255 }
255 }
256
256
257 h1:hover > a.permalink,
257 h1:hover > a.permalink,
258 h2:hover > a.permalink,
258 h2:hover > a.permalink,
259 h3:hover > a.permalink,
259 h3:hover > a.permalink,
260 h4:hover > a.permalink,
260 h4:hover > a.permalink,
261 h5:hover > a.permalink,
261 h5:hover > a.permalink,
262 h6:hover > a.permalink,
262 h6:hover > a.permalink,
263 div:hover > a.permalink,
263 div:hover > a.permalink,
264 div:hover > span > a.permalink {
264 div:hover > span > a.permalink {
265 visibility: visible;
265 visibility: visible;
266 }
266 }
267
267
268 nav.navbar #logo {
268 nav.navbar #logo {
269 padding-left: 10px;
269 padding-left: 10px;
270 }
270 }
271
271
272 #content nav.navbar #logo {
272 #content nav.navbar #logo {
273 padding-left: inherit;
273 padding-left: inherit;
274 }
274 }
275
275
276 nav.navbar #logo .navbar-brand img {
276 nav.navbar #logo .navbar-brand img {
277 padding-top: 5px;
277 padding-top: 5px;
278 margin-right: 5px;
278 margin-right: 5px;
279 }
279 }
280
280
281 nav.navbar #logo .navbar-brand {
281 nav.navbar #logo .navbar-brand {
282 font-size: 20px;
282 font-size: 20px;
283 color: white;
283 color: white;
284 float: left;
284 float: left;
285 height: 44px;
285 height: 44px;
286 line-height: 44px;
286 line-height: 44px;
287 }
287 }
288
288
289 #content nav.navbar #logo .navbar-brand {
289 #content nav.navbar #logo .navbar-brand {
290 height: inherit;
290 height: inherit;
291 line-height: inherit;
291 line-height: inherit;
292 }
292 }
293
293
294 nav.navbar ul#logged-user {
294 nav.navbar ul#logged-user {
295 margin-bottom: 5px !important;
295 margin-bottom: 5px !important;
296 border-radius: 0px 0px 8px 8px;
296 border-radius: 0px 0px 8px 8px;
297 height: 37px;
297 height: 37px;
298 background-color: #577632;
298 background-color: #577632;
299 background-repeat: repeat-x;
299 background-repeat: repeat-x;
300 background-image: linear-gradient(to bottom, #577632, #577632);
300 background-image: linear-gradient(to bottom, #577632, #577632);
301 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
301 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
302 }
302 }
303
303
304 nav.navbar ul#logged-user li {
304 nav.navbar ul#logged-user li {
305 list-style: none;
305 list-style: none;
306 float: left;
306 float: left;
307 margin: 8px 0 0;
307 margin: 8px 0 0;
308 padding: 4px 12px;
308 padding: 4px 12px;
309 border-left: 1px solid #576622;
309 border-left: 1px solid #576622;
310 }
310 }
311
311
312 nav.navbar ul#logged-user li.first {
312 nav.navbar ul#logged-user li.first {
313 border-left: none;
313 border-left: none;
314 margin: 4px;
314 margin: 4px;
315 }
315 }
316
316
317 nav.navbar ul#logged-user li.first div.gravatar {
317 nav.navbar ul#logged-user li.first div.gravatar {
318 margin-top: -2px;
318 margin-top: -2px;
319 }
319 }
320
320
321 nav.navbar ul#logged-user li.first div.account {
321 nav.navbar ul#logged-user li.first div.account {
322 padding-top: 4px;
322 padding-top: 4px;
323 float: left;
323 float: left;
324 }
324 }
325
325
326 nav.navbar ul#logged-user li.last {
326 nav.navbar ul#logged-user li.last {
327 border-right: none;
327 border-right: none;
328 }
328 }
329
329
330 nav.navbar ul#logged-user li a {
330 nav.navbar ul#logged-user li a {
331 color: #fff;
331 color: #fff;
332 font-weight: 700;
332 font-weight: 700;
333 text-decoration: none;
333 text-decoration: none;
334 }
334 }
335
335
336 nav.navbar ul#logged-user li a:hover {
336 nav.navbar ul#logged-user li a:hover {
337 text-decoration: underline;
337 text-decoration: underline;
338 }
338 }
339
339
340 nav.navbar ul#logged-user li.highlight a {
340 nav.navbar ul#logged-user li.highlight a {
341 color: #fff;
341 color: #fff;
342 }
342 }
343
343
344 nav.navbar ul#logged-user li.highlight a:hover {
344 nav.navbar ul#logged-user li.highlight a:hover {
345 color: #FFF;
345 color: #FFF;
346 }
346 }
347 nav.navbar {
347 nav.navbar {
348 min-height: 44px;
348 min-height: 44px;
349 clear: both;
349 clear: both;
350 position: relative;
350 position: relative;
351 background-color: #577632;
351 background-color: #577632;
352 background-repeat: repeat-x;
352 background-repeat: repeat-x;
353 background-image: linear-gradient(to bottom, #577632, #577632);
353 background-image: linear-gradient(to bottom, #577632, #577632);
354 margin: 0;
354 margin: 0;
355 padding: 0;
355 padding: 0;
356 display: block;
356 display: block;
357 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
357 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
358 border-radius: 0px 0px 4px 4px;
358 border-radius: 0px 0px 4px 4px;
359 }
359 }
360
360
361 .header-pos-fix,
361 .header-pos-fix,
362 .anchor {
362 .anchor {
363 margin-top: -46px;
363 margin-top: -46px;
364 padding-top: 46px;
364 padding-top: 46px;
365 }
365 }
366
366
367 nav.navbar #home a {
367 nav.navbar #home a {
368 height: 40px;
368 height: 40px;
369 width: 46px;
369 width: 46px;
370 display: block;
370 display: block;
371 background-position: 0 0;
371 background-position: 0 0;
372 margin: 0;
372 margin: 0;
373 padding: 0;
373 padding: 0;
374 }
374 }
375
375
376 nav.navbar #home a:hover {
376 nav.navbar #home a:hover {
377 background-position: 0 -40px;
377 background-position: 0 -40px;
378 }
378 }
379
379
380 nav.navbar #logo {
380 nav.navbar #logo {
381 float: left;
381 float: left;
382 position: absolute;
382 position: absolute;
383 }
383 }
384
384
385 nav.navbar #logo h1 {
385 nav.navbar #logo h1 {
386 color: #FFF;
386 color: #FFF;
387 font-size: 20px;
387 font-size: 20px;
388 margin: 12px 0 0 13px;
388 margin: 12px 0 0 13px;
389 padding: 0;
389 padding: 0;
390 }
390 }
391
391
392 nav.navbar #logo a {
392 nav.navbar #logo a {
393 color: #fff;
393 color: #fff;
394 text-decoration: none;
394 text-decoration: none;
395 }
395 }
396
396
397 nav.navbar #logo a:hover {
397 nav.navbar #logo a:hover {
398 color: #bfe3ff;
398 color: #bfe3ff;
399 }
399 }
400
400
401 nav.navbar #quick {
401 nav.navbar #quick {
402 position: relative;
402 position: relative;
403 float: right;
403 float: right;
404 list-style-type: none;
404 list-style-type: none;
405 list-style-position: outside;
405 list-style-position: outside;
406 margin: 4px 8px 0 0;
406 margin: 4px 8px 0 0;
407 padding: 0;
407 padding: 0;
408 border-radius: 4px;
408 border-radius: 4px;
409 }
409 }
410
410
411 nav.navbar #quick li span.short {
411 nav.navbar #quick li span.short {
412 padding: 9px 6px 8px 6px;
412 padding: 9px 6px 8px 6px;
413 }
413 }
414
414
415 nav.navbar #quick li span {
415 nav.navbar #quick li span {
416 display: inline;
416 display: inline;
417 margin: 0;
417 margin: 0;
418 }
418 }
419
419
420 nav.navbar #quick li span.normal {
420 nav.navbar #quick li span.normal {
421 border: none;
421 border: none;
422 padding: 10px 12px 8px;
422 padding: 10px 12px 8px;
423 }
423 }
424
424
425 nav.navbar #quick li .icon {
425 nav.navbar #quick li .icon {
426 border-left: none;
426 border-left: none;
427 padding-left: 10px;
427 padding-left: 10px;
428 display: inline;
428 display: inline;
429 }
429 }
430
430
431 nav.navbar #quick li .icon img {
431 nav.navbar #quick li .icon img {
432 vertical-align: middle;
432 vertical-align: middle;
433 margin-bottom: 2px;
433 margin-bottom: 2px;
434 }
434 }
435
435
436 nav.navbar #quick ul.repo_switcher {
436 nav.navbar #quick ul.repo_switcher {
437 max-height: 275px;
437 max-height: 275px;
438 overflow-x: hidden;
438 overflow-x: hidden;
439 overflow-y: auto;
439 overflow-y: auto;
440 }
440 }
441
441
442 nav.navbar #quick ul.repo_switcher li.qfilter_rs {
442 nav.navbar #quick ul.repo_switcher li.qfilter_rs {
443 padding: 2px 3px;
443 padding: 2px 3px;
444 padding-right: 17px;
444 padding-right: 17px;
445 }
445 }
446
446
447 nav.navbar #quick ul.repo_switcher li.qfilter_rs input {
447 nav.navbar #quick ul.repo_switcher li.qfilter_rs input {
448 width: 100%;
448 width: 100%;
449 border-radius: 10px;
449 border-radius: 10px;
450 padding: 2px 7px;
450 padding: 2px 7px;
451 }
451 }
452
452
453 nav.navbar #quick .repo_switcher_type {
453 nav.navbar #quick .repo_switcher_type {
454 position: absolute;
454 position: absolute;
455 left: 0;
455 left: 0;
456 top: 9px;
456 top: 9px;
457 margin: 0px 2px 0px 2px;
457 margin: 0px 2px 0px 2px;
458 }
458 }
459
459
460 .navbar-toggle {
460 .navbar-toggle {
461 display: none;
461 display: none;
462 }
462 }
463
463
464 .groups_breadcrumbs a {
464 .groups_breadcrumbs a {
465 color: #fff;
465 color: #fff;
466 }
466 }
467
467
468 .groups_breadcrumbs a:hover {
468 .groups_breadcrumbs a:hover {
469 color: #bfe3ff;
469 color: #bfe3ff;
470 text-decoration: none;
470 text-decoration: none;
471 }
471 }
472
472
473 .dt_repo {
473 .dt_repo {
474 white-space: nowrap;
474 white-space: nowrap;
475 color: #577632;
475 color: #577632;
476 }
476 }
477
477
478 .dt_repo_pending {
478 .dt_repo_pending {
479 opacity: 0.5;
479 opacity: 0.5;
480 }
480 }
481
481
482 .dt_repo i.icon-keyhole-circled,
482 .dt_repo i.icon-keyhole-circled,
483 .dt_repo i.icon-globe
483 .dt_repo i.icon-globe
484 {
484 {
485 font-size: 16px;
485 font-size: 16px;
486 vertical-align: -2px;
486 vertical-align: -2px;
487 margin: 0px 1px 0px 3px;
487 margin: 0px 1px 0px 3px;
488 }
488 }
489
489
490 .dt_repo a {
490 .dt_repo a {
491 text-decoration: none;
491 text-decoration: none;
492 }
492 }
493
493
494 .dt_repo .dt_repo_name:hover {
494 .dt_repo .dt_repo_name:hover {
495 text-decoration: underline;
495 text-decoration: underline;
496 }
496 }
497
497
498 #content #left {
498 #content #left {
499 left: 0;
499 left: 0;
500 width: 280px;
500 width: 280px;
501 position: absolute;
501 position: absolute;
502 }
502 }
503
503
504 #content #right {
504 #content #right {
505 margin: 0 60px 10px 290px;
505 margin: 0 60px 10px 290px;
506 }
506 }
507
507
508 #content nav.navbar,
508 #content nav.navbar,
509 div.panel {
509 div.panel {
510 clear: both;
510 clear: both;
511 background: #fff;
511 background: #fff;
512 margin: 0 0 10px;
512 margin: 0 0 10px;
513 padding: 0 0 10px;
513 padding: 0 0 10px;
514 border-radius: 4px 4px 4px 4px;
514 border-radius: 4px 4px 4px 4px;
515 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
515 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
516 }
516 }
517
517
518 div.panel div.panel-heading {
518 div.panel div.panel-heading {
519 clear: both;
519 clear: both;
520 overflow: hidden;
520 overflow: hidden;
521 background-color: #577632;
521 background-color: #577632;
522 background-repeat: repeat-x;
522 background-repeat: repeat-x;
523 background-image: linear-gradient(to bottom, #577632, #577632);
523 background-image: linear-gradient(to bottom, #577632, #577632);
524 margin: 0 0 20px;
524 margin: 0 0 20px;
525 padding: 10px 20px;
525 padding: 10px 20px;
526 border-radius: 4px 4px 0 0;
526 border-radius: 4px 4px 0 0;
527 }
527 }
528
528
529 #content div.panel div.panel-heading a {
529 #content div.panel div.panel-heading a {
530 color: #FFFFFF;
530 color: #FFFFFF;
531 }
531 }
532
532
533 #content div.panel div.panel-heading ul.links li {
533 #content div.panel div.panel-heading ul.links li {
534 list-style: none;
534 list-style: none;
535 float: left;
535 float: left;
536 margin: 0;
536 margin: 0;
537 padding: 0;
537 padding: 0;
538 }
538 }
539
539
540 #content div.panel div.panel-heading ul.links li a {
540 #content div.panel div.panel-heading ul.links li a {
541 font-size: 13px;
541 font-size: 13px;
542 font-weight: 700;
542 font-weight: 700;
543 height: 1%;
543 height: 1%;
544 text-decoration: none;
544 text-decoration: none;
545 }
545 }
546
546
547 #content div.panel div.panel-heading ul.links.nav-tabs li a {
547 #content div.panel div.panel-heading ul.links.nav-tabs li a {
548 float: left;
548 float: left;
549 color: #fff;
549 color: #fff;
550 margin: 0;
550 margin: 0;
551 padding: 11px 10px 11px 10px;
551 padding: 11px 10px 11px 10px;
552 }
552 }
553
553
554 .clearfix::before, .clearfix::after, .dl-horizontal dd::before, .dl-horizontal dd::after, .container::before, .container::after, .container-fluid::before, .container-fluid::after, .row::before, .row::after, .form-horizontal .form-group::before, .form-horizontal .form-group::after, .btn-toolbar::before, .btn-toolbar::after, .btn-group-vertical > .btn-group::before, .btn-group-vertical > .btn-group::after, .nav::before, .nav::after, .navbar::before, .navbar::after, .navbar-header::before, .navbar-header::after, .navbar-collapse::before, .navbar-collapse::after, .pager::before, .pager::after, .panel::before, .panel::after, .panel-body::before, .panel-body::after, .modal-header::before, .modal-header::after, .modal-footer::before, .modal-footer::after, td.inline-comments::before, td.inline-comments::after {
554 .clearfix::before, .clearfix::after, .dl-horizontal dd::before, .dl-horizontal dd::after, .container::before, .container::after, .container-fluid::before, .container-fluid::after, .row::before, .row::after, .form-horizontal .form-group::before, .form-horizontal .form-group::after, .btn-toolbar::before, .btn-toolbar::after, .btn-group-vertical > .btn-group::before, .btn-group-vertical > .btn-group::after, .nav::before, .nav::after, .navbar::before, .navbar::after, .navbar-header::before, .navbar-header::after, .navbar-collapse::before, .navbar-collapse::after, .pager::before, .pager::after, .panel::before, .panel::after, .panel-body::before, .panel-body::after, .modal-header::before, .modal-header::after, .modal-footer::before, .modal-footer::after, td.inline-comments::before, td.inline-comments::after {
555 content: " ";
555 content: " ";
556 display: table;
556 display: table;
557 }
557 }
558
558
559 .clearfix::after, .dl-horizontal dd::after, .container::after, .container-fluid::after, .row::after, .form-horizontal .form-group::after, .btn-toolbar::after, .btn-group-vertical > .btn-group::after, .nav::after, .navbar::after, .navbar-header::after, .navbar-collapse::after, .pager::after, .panel::after, .panel-body::after, .modal-header::after, .modal-footer::after, td.inline-comments::after {
559 .clearfix::after, .dl-horizontal dd::after, .container::after, .container-fluid::after, .row::after, .form-horizontal .form-group::after, .btn-toolbar::after, .btn-group-vertical > .btn-group::after, .nav::after, .navbar::after, .navbar-header::after, .navbar-collapse::after, .pager::after, .panel::after, .panel-body::after, .modal-header::after, .modal-footer::after, td.inline-comments::after {
560 clear: both;
560 clear: both;
561 }
561 }
562
562
563 /* avoid conflict with .container in changeset tables */
563 /* avoid conflict with .container in changeset tables */
564 #content div.panel table .container::before,
564 #content div.panel table .container::before,
565 #content div.panel table .container::after {
565 #content div.panel table .container::after {
566 content: inherit;
566 content: inherit;
567 display: inherit;
567 display: inherit;
568 }
568 }
569
569
570 .pull-left {
570 .pull-left {
571 float: left;
571 float: left;
572 }
572 }
573
573
574 .pull-right {
574 .pull-right {
575 float: right;
575 float: right;
576 }
576 }
577
577
578 #content div.panel div.panel-heading .pull-left,
578 #content div.panel div.panel-heading .pull-left,
579 #content div.panel div.panel-heading .pull-left a,
579 #content div.panel div.panel-heading .pull-left a,
580 #content div.panel div.panel-heading .pull-right,
580 #content div.panel div.panel-heading .pull-right,
581 #content div.panel div.panel-heading .pull-right a {
581 #content div.panel div.panel-heading .pull-right a {
582 color: white;
582 color: white;
583 }
583 }
584
584
585 #content div.panel h1,
585 #content div.panel h1,
586 #content div.panel h2,
586 #content div.panel h2,
587 #content div.panel h3,
587 #content div.panel h3,
588 #content div.panel h4,
588 #content div.panel h4,
589 #content div.panel h5,
589 #content div.panel h5,
590 #content div.panel h6,
590 #content div.panel h6,
591 #content div.panel div.h1,
591 #content div.panel div.h1,
592 #content div.panel div.h2,
592 #content div.panel div.h2,
593 #content div.panel div.h3,
593 #content div.panel div.h3,
594 #content div.panel div.h4,
594 #content div.panel div.h4,
595 #content div.panel div.h5,
595 #content div.panel div.h5,
596 #content div.panel div.h6 {
596 #content div.panel div.h6 {
597 clear: both;
597 clear: both;
598 overflow: hidden;
598 overflow: hidden;
599 margin: 8px 0 3px;
599 margin: 8px 0 3px;
600 padding-bottom: 2px;
600 padding-bottom: 2px;
601 }
601 }
602
602
603 #content div.panel p {
603 #content div.panel p {
604 color: #5f5f5f;
604 color: #5f5f5f;
605 font-size: 12px;
605 font-size: 12px;
606 line-height: 150%;
606 line-height: 150%;
607 margin: 0 24px 10px;
607 margin: 0 24px 10px;
608 padding: 0;
608 padding: 0;
609 }
609 }
610
610
611 #content div.panel blockquote {
611 #content div.panel blockquote {
612 border-left: 4px solid #DDD;
612 border-left: 4px solid #DDD;
613 color: #5f5f5f;
613 color: #5f5f5f;
614 font-size: 11px;
614 font-size: 11px;
615 line-height: 150%;
615 line-height: 150%;
616 margin: 0 34px;
616 margin: 0 34px;
617 padding: 0 0 0 14px;
617 padding: 0 0 0 14px;
618 }
618 }
619
619
620 #content div.panel blockquote p {
620 #content div.panel blockquote p {
621 margin: 10px 0;
621 margin: 10px 0;
622 padding: 0;
622 padding: 0;
623 }
623 }
624
624
625 #content div.panel dl {
625 #content div.panel dl {
626 margin: 10px 0px;
626 margin: 10px 0px;
627 }
627 }
628
628
629 #content div.panel dt {
629 #content div.panel dt {
630 font-size: 12px;
630 font-size: 12px;
631 margin: 0;
631 margin: 0;
632 }
632 }
633
633
634 #content div.panel dd {
634 #content div.panel dd {
635 font-size: 12px;
635 font-size: 12px;
636 margin: 0;
636 margin: 0;
637 padding: 8px 0 8px 15px;
637 padding: 8px 0 8px 15px;
638 }
638 }
639
639
640 #content div.panel li {
640 #content div.panel li {
641 font-size: 12px;
641 font-size: 12px;
642 padding: 4px 0;
642 padding: 4px 0;
643 }
643 }
644
644
645 #content div.panel ul.disc,
645 #content div.panel ul.disc,
646 #content div.panel ul.circle {
646 #content div.panel ul.circle {
647 margin: 10px 24px 10px 38px;
647 margin: 10px 24px 10px 38px;
648 }
648 }
649
649
650 #content div.panel ul.square {
650 #content div.panel ul.square {
651 margin: 10px 24px 10px 40px;
651 margin: 10px 24px 10px 40px;
652 }
652 }
653
653
654 #content div.panel img.left {
654 #content div.panel img.left {
655 border: none;
655 border: none;
656 float: left;
656 float: left;
657 margin: 10px 10px 10px 0;
657 margin: 10px 10px 10px 0;
658 }
658 }
659
659
660 #content div.panel img.right {
660 #content div.panel img.right {
661 border: none;
661 border: none;
662 float: right;
662 float: right;
663 margin: 10px 0 10px 10px;
663 margin: 10px 0 10px 10px;
664 }
664 }
665
665
666 #content div.panel div.messages {
666 #content div.panel div.messages {
667 clear: both;
667 clear: both;
668 overflow: hidden;
668 overflow: hidden;
669 margin: 0 20px;
669 margin: 0 20px;
670 padding: 0;
670 padding: 0;
671 }
671 }
672
672
673 #content div.panel div.message {
673 #content div.panel div.message {
674 float: left;
674 float: left;
675 overflow: hidden;
675 overflow: hidden;
676 margin: 0;
676 margin: 0;
677 padding: 5px 0;
677 padding: 5px 0;
678 white-space: pre-wrap;
678 white-space: pre-wrap;
679 }
679 }
680 #content div.panel #changeset_content div.message {
680 #content div.panel #changeset_content div.message {
681 padding: 15px 0;
681 padding: 15px 0;
682 }
682 }
683 #content div.panel div.expand {
683 #content div.panel div.expand {
684 width: 110%;
684 width: 110%;
685 height: 14px;
685 height: 14px;
686 font-size: 10px;
686 font-size: 10px;
687 text-align: center;
687 text-align: center;
688 cursor: pointer;
688 cursor: pointer;
689 color: #666;
689 color: #666;
690 background: linear-gradient(to bottom,rgba(255,255,255,0),rgba(64,96,128,0.1));
690 background: linear-gradient(to bottom,rgba(255,255,255,0),rgba(64,96,128,0.1));
691 display: none;
691 display: none;
692 overflow: hidden;
692 overflow: hidden;
693 }
693 }
694 #content div.panel div.expand .expandtext {
694 #content div.panel div.expand .expandtext {
695 background-color: #ffffff;
695 background-color: #ffffff;
696 padding: 2px;
696 padding: 2px;
697 border-radius: 2px;
697 border-radius: 2px;
698 }
698 }
699
699
700 #content div.panel div.message a {
700 #content div.panel div.message a {
701 font-weight: 400 !important;
701 font-weight: 400 !important;
702 }
702 }
703
703
704 #content div.panel div.message div.image {
704 #content div.panel div.message div.image {
705 float: left;
705 float: left;
706 margin: 9px 0 0 5px;
706 margin: 9px 0 0 5px;
707 padding: 6px;
707 padding: 6px;
708 }
708 }
709
709
710 #content div.panel div.message div.image img {
710 #content div.panel div.message div.image img {
711 vertical-align: middle;
711 vertical-align: middle;
712 margin: 0;
712 margin: 0;
713 }
713 }
714
714
715 #content div.panel div.message div.text {
715 #content div.panel div.message div.text {
716 float: left;
716 float: left;
717 margin: 0;
717 margin: 0;
718 padding: 9px 6px;
718 padding: 9px 6px;
719 }
719 }
720
720
721 #content div.panel div.message div.text h1,
721 #content div.panel div.message div.text h1,
722 #content div.panel div.message div.text h2,
722 #content div.panel div.message div.text h2,
723 #content div.panel div.message div.text h3,
723 #content div.panel div.message div.text h3,
724 #content div.panel div.message div.text h4,
724 #content div.panel div.message div.text h4,
725 #content div.panel div.message div.text h5,
725 #content div.panel div.message div.text h5,
726 #content div.panel div.message div.text h6 {
726 #content div.panel div.message div.text h6 {
727 border: none;
727 border: none;
728 margin: 0;
728 margin: 0;
729 padding: 0;
729 padding: 0;
730 }
730 }
731
731
732 #content div.panel div.message div.text span {
732 #content div.panel div.message div.text span {
733 height: 1%;
733 height: 1%;
734 display: block;
734 display: block;
735 margin: 0;
735 margin: 0;
736 padding: 5px 0 0;
736 padding: 5px 0 0;
737 }
737 }
738
738
739 #content div.panel div.message-error {
739 #content div.panel div.message-error {
740 height: 1%;
740 height: 1%;
741 clear: both;
741 clear: both;
742 overflow: hidden;
742 overflow: hidden;
743 background: #FBE3E4;
743 background: #FBE3E4;
744 border: 1px solid #FBC2C4;
744 border: 1px solid #FBC2C4;
745 color: #860006;
745 color: #860006;
746 }
746 }
747
747
748 #content div.panel div.message-error h6 {
748 #content div.panel div.message-error h6 {
749 color: #860006;
749 color: #860006;
750 }
750 }
751
751
752 #content div.panel div.message-warning {
752 #content div.panel div.message-warning {
753 height: 1%;
753 height: 1%;
754 clear: both;
754 clear: both;
755 overflow: hidden;
755 overflow: hidden;
756 background: #FFF6BF;
756 background: #FFF6BF;
757 border: 1px solid #FFD324;
757 border: 1px solid #FFD324;
758 color: #5f5200;
758 color: #5f5200;
759 }
759 }
760
760
761 #content div.panel div.message-warning h6 {
761 #content div.panel div.message-warning h6 {
762 color: #5f5200;
762 color: #5f5200;
763 }
763 }
764
764
765 #content div.panel div.message-notice {
765 #content div.panel div.message-notice {
766 height: 1%;
766 height: 1%;
767 clear: both;
767 clear: both;
768 overflow: hidden;
768 overflow: hidden;
769 background: #8FBDE0;
769 background: #8FBDE0;
770 border: 1px solid #6BACDE;
770 border: 1px solid #6BACDE;
771 color: #003863;
771 color: #003863;
772 }
772 }
773
773
774 #content div.panel div.message-notice h6 {
774 #content div.panel div.message-notice h6 {
775 color: #003863;
775 color: #003863;
776 }
776 }
777
777
778 #content div.panel div.message-success {
778 #content div.panel div.message-success {
779 height: 1%;
779 height: 1%;
780 clear: both;
780 clear: both;
781 overflow: hidden;
781 overflow: hidden;
782 background: #E6EFC2;
782 background: #E6EFC2;
783 border: 1px solid #C6D880;
783 border: 1px solid #C6D880;
784 color: #4e6100;
784 color: #4e6100;
785 }
785 }
786
786
787 #content div.panel div.message-success h6 {
787 #content div.panel div.message-success h6 {
788 color: #4e6100;
788 color: #4e6100;
789 }
789 }
790
790
791 #content div.panel div.form div.form-horizontal div.form-group {
791 #content div.panel div.form div.form-horizontal div.form-group {
792 height: 1%;
792 height: 1%;
793 min-height: 12px;
793 min-height: 12px;
794 border-bottom: 1px solid #DDD;
794 border-bottom: 1px solid #DDD;
795 clear: both;
795 clear: both;
796 padding: 0;
796 padding: 0;
797 margin: 10px 0;
797 margin: 10px 0;
798 }
798 }
799
799
800 #content div.panel div.form div.form-horizontal div.form-group-first {
800 #content div.panel div.form div.form-horizontal div.form-group-first {
801 padding: 0 0 10px;
801 padding: 0 0 10px;
802 }
802 }
803
803
804 #content div.panel div.form div.form-horizontal div.form-group-noborder {
804 #content div.panel div.form div.form-horizontal div.form-group-noborder {
805 border-bottom: 0 !important;
805 border-bottom: 0 !important;
806 }
806 }
807
807
808 #content div.panel div.form div.form-horizontal div.form-group span.error-message {
808 #content div.panel div.form div.form-horizontal div.form-group span.error-message {
809 height: 1%;
809 height: 1%;
810 display: inline-block;
810 display: inline-block;
811 color: red;
811 color: red;
812 margin: 8px 0 0 4px;
812 margin: 8px 0 0 4px;
813 padding: 0;
813 padding: 0;
814 }
814 }
815
815
816 #content div.panel div.form div.form-horizontal div.form-group span.success {
816 #content div.panel div.form div.form-horizontal div.form-group span.success {
817 height: 1%;
817 height: 1%;
818 display: block;
818 display: block;
819 color: #316309;
819 color: #316309;
820 margin: 8px 0 0;
820 margin: 8px 0 0;
821 padding: 0;
821 padding: 0;
822 }
822 }
823
823
824 #content div.panel div.form div.form-horizontal div.form-group > label {
824 #content div.panel div.form div.form-horizontal div.form-group > label {
825 margin: 0;
825 margin: 0;
826 }
826 }
827
827
828 #content div.panel div.form div.form-horizontal div.form-group > label {
828 #content div.panel div.form div.form-horizontal div.form-group > label {
829 width: 155px;
829 width: 155px;
830 position: absolute;
830 position: absolute;
831 margin: 0;
831 margin: 0;
832 padding: 0px 0 0 0px;
832 padding: 0px 0 0 0px;
833 }
833 }
834
834
835 #content div.panel div.form div.form-horizontal div.form-group > label {
835 #content div.panel div.form div.form-horizontal div.form-group > label {
836 color: #393939;
836 color: #393939;
837 font-weight: 700;
837 font-weight: 700;
838 }
838 }
839
839
840 #content div.panel div.form div.form-horizontal div.form-group > div {
840 #content div.panel div.form div.form-horizontal div.form-group > div {
841 margin: 0 20px 0 200px;
841 margin: 0 20px 0 200px;
842 }
842 }
843
843
844 #content div.panel div.form div.form-horizontal div.form-group > div.summary,
844 #content div.panel div.form div.form-horizontal div.form-group > div.summary,
845 #content div.panel div.form div.form-horizontal div.form-group > div.summary-short {
845 #content div.panel div.form div.form-horizontal div.form-group > div.summary-short {
846 margin: 10px 20px 10px 110px;
846 margin: 10px 20px 10px 110px;
847 }
847 }
848 #content div.panel div.form div.form-horizontal div.form-group > div.summary-short input {
848 #content div.panel div.form div.form-horizontal div.form-group > div.summary-short input {
849 margin: 0;
849 margin: 0;
850 }
850 }
851 #content div.panel div.form div.form-horizontal div.form-group > div.file {
851 #content div.panel div.form div.form-horizontal div.form-group > div.file {
852 margin: 0 20px 0 200px;
852 margin: 0 20px 0 200px;
853 }
853 }
854
854
855 #content div.panel div.form div.form-horizontal div.form-group > label > input[type=text],
855 #content div.panel div.form div.form-horizontal div.form-group > label > input[type=text],
856 #content div.panel div.form div.form-horizontal div.form-group > label > input[type=password],
856 #content div.panel div.form div.form-horizontal div.form-group > label > input[type=password],
857 #content div.panel div.form div.form-horizontal div.form-group > div input[type=text],
857 #content div.panel div.form div.form-horizontal div.form-group > div input[type=text],
858 #content div.panel div.form div.form-horizontal div.form-group > div input[type=password],
858 #content div.panel div.form div.form-horizontal div.form-group > div input[type=password],
859 #content div.panel div.form div.form-horizontal div.form-group > label > textarea,
859 #content div.panel div.form div.form-horizontal div.form-group > label > textarea,
860 #content div.panel div.form div.form-horizontal div.form-group > div textarea,
860 #content div.panel div.form div.form-horizontal div.form-group > div textarea,
861 .reviewer_ac input {
861 .reviewer_ac input {
862 background: #FFF;
862 background: #FFF;
863 border-top: 1px solid #b3b3b3;
863 border-top: 1px solid #b3b3b3;
864 border-left: 1px solid #b3b3b3;
864 border-left: 1px solid #b3b3b3;
865 border-right: 1px solid #eaeaea;
865 border-right: 1px solid #eaeaea;
866 border-bottom: 1px solid #eaeaea;
866 border-bottom: 1px solid #eaeaea;
867 color: #000;
867 color: #000;
868 font-size: 12px;
868 font-size: 12px;
869 margin: 5px 0 10px;
869 margin: 5px 0 10px;
870 padding: 7px 7px 6px;
870 padding: 7px 7px 6px;
871 }
871 }
872
872
873 #content div.panel div.form div.form-horizontal div.form-group > div input#clone_url,
873 #content div.panel div.form div.form-horizontal div.form-group > div input#clone_url,
874 #content div.panel div.form div.form-horizontal div.form-group > div input#clone_url_id
874 #content div.panel div.form div.form-horizontal div.form-group > div input#clone_url_id
875 {
875 {
876 font-size: 14px;
876 font-size: 14px;
877 padding: 0 2px;
877 padding: 0 2px;
878 }
878 }
879
879
880 #content div.panel div.form div.form-horizontal div.form-group div.file input {
880 #content div.panel div.form div.form-horizontal div.form-group div.file input {
881 background: none repeat scroll 0 0 #FFFFFF;
881 background: none repeat scroll 0 0 #FFFFFF;
882 border-color: #B3B3B3 #EAEAEA #EAEAEA #B3B3B3;
882 border-color: #B3B3B3 #EAEAEA #EAEAEA #B3B3B3;
883 border-style: solid;
883 border-style: solid;
884 border-width: 1px;
884 border-width: 1px;
885 color: #000000;
885 color: #000000;
886 font-size: 12px;
886 font-size: 12px;
887 margin: 0;
887 margin: 0;
888 padding: 7px 7px 6px;
888 padding: 7px 7px 6px;
889 }
889 }
890
890
891 input[readonly],
891 input[readonly],
892 input.disabled {
892 input.disabled {
893 background-color: #F5F5F5 !important;
893 background-color: #F5F5F5 !important;
894 }
894 }
895
895
896 #content div.panel div.form div.form-horizontal div.form-group > div.form-inline,
896 #content div.panel div.form div.form-horizontal div.form-group > div.form-inline,
897 #content div.panel div.form div.form-horizontal div.form-group > div.form-inline,
897 #content div.panel div.form div.form-horizontal div.form-group > div.form-inline,
898 #content div.panel div.form div.form-horizontal div.form-group > div.form-inline {
898 #content div.panel div.form div.form-horizontal div.form-group > div.form-inline {
899 display: inline;
899 display: inline;
900 }
900 }
901
901
902 #content div.panel div.form div.form-horizontal div.form-group > div select.form-control,
902 #content div.panel div.form div.form-horizontal div.form-group > div select.form-control,
903 #content div.panel div.form div.form-horizontal div.form-group > div div.form-control.select2-container,
903 #content div.panel div.form div.form-horizontal div.form-group > div div.form-control.select2-container,
904 #content div.panel div.form div.form-horizontal div.form-group > div input.form-control {
904 #content div.panel div.form div.form-horizontal div.form-group > div input.form-control {
905 width: 100%;
905 width: 100%;
906 margin: 5px 0 10px;
906 margin: 5px 0 10px;
907 }
907 }
908
908
909 #content div.panel div.form div.form-horizontal div.form-group > div.form-inline select.form-control,
909 #content div.panel div.form div.form-horizontal div.form-group > div.form-inline select.form-control,
910 #content div.panel div.form div.form-horizontal div.form-group > div.form-inline div.form-control.select2-container,
910 #content div.panel div.form div.form-horizontal div.form-group > div.form-inline div.form-control.select2-container,
911 #content div.panel div.form div.form-horizontal div.form-group > div.form-inline input.form-control {
911 #content div.panel div.form div.form-horizontal div.form-group > div.form-inline input.form-control {
912 width: inherit;
912 width: inherit;
913 }
913 }
914
914
915 #content div.panel div.form div.form-horizontal div.form-group > div input.date {
915 #content div.panel div.form div.form-horizontal div.form-group > div input.date {
916 width: 177px;
916 width: 177px;
917 }
917 }
918
918
919 #content div.panel div.form div.form-horizontal div.form-group > div input.button {
919 #content div.panel div.form div.form-horizontal div.form-group > div input.button {
920 background: #D4D0C8;
920 background: #D4D0C8;
921 border-top: 1px solid #FFF;
921 border-top: 1px solid #FFF;
922 border-left: 1px solid #FFF;
922 border-left: 1px solid #FFF;
923 border-right: 1px solid #404040;
923 border-right: 1px solid #404040;
924 border-bottom: 1px solid #404040;
924 border-bottom: 1px solid #404040;
925 color: #000;
925 color: #000;
926 margin: 0;
926 margin: 0;
927 padding: 4px 8px;
927 padding: 4px 8px;
928 }
928 }
929
929
930 #content div.panel div.form div.form-horizontal div.form-group > div textarea {
930 #content div.panel div.form div.form-horizontal div.form-group > div textarea {
931 width: 100%;
931 width: 100%;
932 height: 220px;
932 height: 220px;
933 overflow-y: auto;
933 overflow-y: auto;
934 outline: none;
934 outline: none;
935 }
935 }
936
936
937 #content div.panel div.form div.form-horizontal div.form-group input[type=text]:focus,
937 #content div.panel div.form div.form-horizontal div.form-group input[type=text]:focus,
938 #content div.panel div.form div.form-horizontal div.form-group input[type=password]:focus,
938 #content div.panel div.form div.form-horizontal div.form-group input[type=password]:focus,
939 #content div.panel div.form div.form-horizontal div.form-group input[type=file]:focus,
939 #content div.panel div.form div.form-horizontal div.form-group input[type=file]:focus,
940 #content div.panel div.form div.form-horizontal div.form-group textarea:focus,
940 #content div.panel div.form div.form-horizontal div.form-group textarea:focus,
941 #content div.panel div.form div.form-horizontal div.form-group select:focus,
941 #content div.panel div.form div.form-horizontal div.form-group select:focus,
942 .reviewer_ac input:focus {
942 .reviewer_ac input:focus {
943 background: #f6f6f6;
943 background: #f6f6f6;
944 border-color: #666;
944 border-color: #666;
945 }
945 }
946
946
947 .reviewer_ac {
947 .reviewer_ac {
948 padding: 10px
948 padding: 10px
949 }
949 }
950
950
951 div.form div.form-horizontal div.form-group div.button {
951 div.form div.form-horizontal div.form-group div.button {
952 margin: 0;
952 margin: 0;
953 padding: 0 0 0 8px;
953 padding: 0 0 0 8px;
954 }
954 }
955
955
956 #content div.panel table.table {
956 #content div.panel table.table {
957 border: 1px solid transparent;
957 border: 1px solid transparent;
958 }
958 }
959
959
960 #content div.panel table {
960 #content div.panel table {
961 width: 100%;
961 width: 100%;
962 border-collapse: separate;
962 border-collapse: separate;
963 margin: 0;
963 margin: 0;
964 padding: 0;
964 padding: 0;
965 border: 1px solid #eee;
965 border: 1px solid #eee;
966 border-radius: 4px;
966 border-radius: 4px;
967 }
967 }
968
968
969 #content div.panel table th {
969 #content div.panel table th {
970 background: #eee;
970 background: #eee;
971 border-bottom: 1px solid #ddd;
971 border-bottom: 1px solid #ddd;
972 padding: 5px 0px 5px 5px;
972 padding: 5px 0px 5px 5px;
973 text-align: left;
973 text-align: left;
974 }
974 }
975
975
976 #content div.panel table th.left {
976 #content div.panel table th.left {
977 text-align: left;
977 text-align: left;
978 }
978 }
979
979
980 #content div.panel table th.right {
980 #content div.panel table th.right {
981 text-align: right;
981 text-align: right;
982 }
982 }
983
983
984 #content div.panel table th.center {
984 #content div.panel table th.center {
985 text-align: center;
985 text-align: center;
986 }
986 }
987
987
988 #content div.panel table th.selected {
988 #content div.panel table th.selected {
989 vertical-align: middle;
989 vertical-align: middle;
990 padding: 0;
990 padding: 0;
991 }
991 }
992
992
993 #content div.panel table td {
993 #content div.panel table td {
994 background: #fff;
994 background: #fff;
995 border-bottom: 1px solid #cdcdcd;
995 border-bottom: 1px solid #cdcdcd;
996 vertical-align: middle;
996 vertical-align: middle;
997 padding: 5px;
997 padding: 5px;
998 }
998 }
999
999
1000 #content div.panel table td.compact {
1000 #content div.panel table td.compact {
1001 padding: 0;
1001 padding: 0;
1002 }
1002 }
1003
1003
1004 #content div.panel table tr.selected td {
1004 #content div.panel table tr.selected td {
1005 background: #FFC;
1005 background: #FFC;
1006 }
1006 }
1007
1007
1008 #content div.panel table td.selected {
1008 #content div.panel table td.selected {
1009 width: 3%;
1009 width: 3%;
1010 text-align: center;
1010 text-align: center;
1011 vertical-align: middle;
1011 vertical-align: middle;
1012 padding: 0;
1012 padding: 0;
1013 }
1013 }
1014
1014
1015 #content div.panel table td.action {
1015 #content div.panel table td.action {
1016 width: 45%;
1016 width: 45%;
1017 text-align: left;
1017 text-align: left;
1018 }
1018 }
1019
1019
1020 #content div.panel table td.date {
1020 #content div.panel table td.date {
1021 width: 33%;
1021 width: 33%;
1022 text-align: center;
1022 text-align: center;
1023 }
1023 }
1024
1024
1025 #content div.panel div.action {
1025 #content div.panel div.action {
1026 float: right;
1026 float: right;
1027 background: #FFF;
1027 background: #FFF;
1028 text-align: right;
1028 text-align: right;
1029 margin: 10px 0 0;
1029 margin: 10px 0 0;
1030 padding: 0;
1030 padding: 0;
1031 }
1031 }
1032
1032
1033 #content div.panel div.action select {
1033 #content div.panel div.action select {
1034 font-size: 11px;
1034 font-size: 11px;
1035 margin: 0;
1035 margin: 0;
1036 }
1036 }
1037
1037
1038 #content div.panel div.action .ui-selectmenu {
1038 #content div.panel div.action .ui-selectmenu {
1039 margin: 0;
1039 margin: 0;
1040 padding: 0;
1040 padding: 0;
1041 }
1041 }
1042
1042
1043 #content div.panel ul.pagination {
1043 #content div.panel ul.pagination {
1044 height: 1%;
1044 height: 1%;
1045 overflow: hidden;
1045 overflow: hidden;
1046 text-align: right;
1046 text-align: right;
1047 margin: 10px 0 0;
1047 margin: 10px 0 0;
1048 padding: 0;
1048 padding: 0;
1049 }
1049 }
1050
1050
1051 #content div.panel ul.pagination > li {
1051 #content div.panel ul.pagination > li {
1052 display: inline;
1052 display: inline;
1053 }
1053 }
1054
1054
1055 #content div.panel ul.pagination > :first-child {
1055 #content div.panel ul.pagination > :first-child {
1056 border-radius: 4px 0px 0px 4px;
1056 border-radius: 4px 0px 0px 4px;
1057 }
1057 }
1058
1058
1059 #content div.panel ul.pagination > :last-child {
1059 #content div.panel ul.pagination > :last-child {
1060 border-radius: 0px 4px 4px 0px;
1060 border-radius: 0px 4px 4px 0px;
1061 border-right: 1px solid #cfcfcf;
1061 border-right: 1px solid #cfcfcf;
1062 }
1062 }
1063
1063
1064 #content div.panel ul.pagination > li {
1064 #content div.panel ul.pagination > li {
1065 height: 1%;
1065 height: 1%;
1066 float: left;
1066 float: left;
1067 background: #ebebeb url("../images/pager.png") repeat-x;
1067 background: #ebebeb url("../images/pager.png") repeat-x;
1068 border-top: 1px solid #dedede;
1068 border-top: 1px solid #dedede;
1069 border-left: 1px solid #cfcfcf;
1069 border-left: 1px solid #cfcfcf;
1070 border-bottom: 1px solid #c4c4c4;
1070 border-bottom: 1px solid #c4c4c4;
1071 color: #4A4A4A;
1071 color: #4A4A4A;
1072 font-weight: 700;
1072 font-weight: 700;
1073 padding: 6px;
1073 padding: 6px;
1074 }
1074 }
1075
1075
1076 #content div.panel ul.pagination > li.active {
1076 #content div.panel ul.pagination > li.active {
1077 background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
1077 background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
1078 border-top: 1px solid #ccc;
1078 border-top: 1px solid #ccc;
1079 border-left: 1px solid #bebebe;
1079 border-left: 1px solid #bebebe;
1080 border-bottom: 1px solid #afafaf;
1080 border-bottom: 1px solid #afafaf;
1081 color: #515151;
1081 color: #515151;
1082 }
1082 }
1083
1083
1084 #content div.panel ul.pagination > a:hover,
1084 #content div.panel ul.pagination > a:hover,
1085 #content div.panel ul.pagination > a:active {
1085 #content div.panel ul.pagination > a:active {
1086 background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
1086 background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
1087 border-top: 1px solid #ccc;
1087 border-top: 1px solid #ccc;
1088 border-left: 1px solid #bebebe;
1088 border-left: 1px solid #bebebe;
1089 border-bottom: 1px solid #afafaf;
1089 border-bottom: 1px solid #afafaf;
1090 text-decoration: none;
1090 text-decoration: none;
1091 }
1091 }
1092
1092
1093 #content div.panel ul.pagination > li a {
1093 #content div.panel ul.pagination > li a {
1094 color: inherit;
1094 color: inherit;
1095 text-decoration: inherit;
1095 text-decoration: inherit;
1096 }
1096 }
1097
1097
1098 #content div.panel div.traffic div.legend {
1098 #content div.panel div.traffic div.legend {
1099 clear: both;
1099 clear: both;
1100 overflow: hidden;
1100 overflow: hidden;
1101 border-bottom: 1px solid #ddd;
1101 border-bottom: 1px solid #ddd;
1102 margin: 0 0 10px;
1102 margin: 0 0 10px;
1103 padding: 0 0 10px;
1103 padding: 0 0 10px;
1104 }
1104 }
1105
1105
1106 #content div.panel div.traffic div.legend h6 {
1106 #content div.panel div.traffic div.legend h6 {
1107 float: left;
1107 float: left;
1108 border: none;
1108 border: none;
1109 margin: 0;
1109 margin: 0;
1110 padding: 0;
1110 padding: 0;
1111 }
1111 }
1112
1112
1113 #content div.panel div.traffic div.legend li {
1113 #content div.panel div.traffic div.legend li {
1114 list-style: none;
1114 list-style: none;
1115 float: left;
1115 float: left;
1116 font-size: 11px;
1116 font-size: 11px;
1117 margin: 0;
1117 margin: 0;
1118 padding: 0 8px 0 4px;
1118 padding: 0 8px 0 4px;
1119 }
1119 }
1120
1120
1121 #content div.panel div.traffic div.legend li.visits {
1121 #content div.panel div.traffic div.legend li.visits {
1122 border-left: 12px solid #edc240;
1122 border-left: 12px solid #edc240;
1123 }
1123 }
1124
1124
1125 #content div.panel div.traffic div.legend li.pageviews {
1125 #content div.panel div.traffic div.legend li.pageviews {
1126 border-left: 12px solid #afd8f8;
1126 border-left: 12px solid #afd8f8;
1127 }
1127 }
1128
1128
1129 #content div.panel div.traffic table {
1129 #content div.panel div.traffic table {
1130 width: auto;
1130 width: auto;
1131 }
1131 }
1132
1132
1133 #content div.panel div.traffic table td {
1133 #content div.panel div.traffic table td {
1134 background: transparent;
1134 background: transparent;
1135 border: none;
1135 border: none;
1136 padding: 2px 3px 3px;
1136 padding: 2px 3px 3px;
1137 }
1137 }
1138
1138
1139 #content div.panel div.traffic table td.legendLabel {
1139 #content div.panel div.traffic table td.legendLabel {
1140 padding: 0 3px 2px;
1140 padding: 0 3px 2px;
1141 }
1141 }
1142
1142
1143 #content div.panel #summary-panel-body {
1143 #content div.panel #summary-panel-body {
1144 position: relative;
1144 position: relative;
1145 }
1145 }
1146
1146
1147 #content div.panel #summary {
1147 #content div.panel #summary {
1148 margin-right: 200px;
1148 margin-right: 200px;
1149 min-height: 240px;
1149 min-height: 240px;
1150 }
1150 }
1151
1151
1152 #summary-menu-stats {
1152 #summary-menu-stats {
1153 float: left;
1153 float: left;
1154 width: 180px;
1154 width: 180px;
1155 position: absolute;
1155 position: absolute;
1156 top: 0;
1156 top: 0;
1157 right: 0;
1157 right: 0;
1158 }
1158 }
1159
1159
1160 #summary-menu-stats ul {
1160 #summary-menu-stats ul {
1161 display: block;
1161 display: block;
1162 background-color: #f9f9f9;
1162 background-color: #f9f9f9;
1163 border: 1px solid #d1d1d1;
1163 border: 1px solid #d1d1d1;
1164 border-radius: 4px;
1164 border-radius: 4px;
1165 }
1165 }
1166
1166
1167 #content #summary-menu-stats li {
1167 #content #summary-menu-stats li {
1168 border-top: 1px solid #d1d1d1;
1168 border-top: 1px solid #d1d1d1;
1169 padding: 0;
1169 padding: 0;
1170 }
1170 }
1171
1171
1172 #content #summary-menu-stats li:hover {
1172 #content #summary-menu-stats li:hover {
1173 background: #f0f0f0;
1173 background: #f0f0f0;
1174 }
1174 }
1175
1175
1176 #content #summary-menu-stats li:first-child {
1176 #content #summary-menu-stats li:first-child {
1177 border-top: none;
1177 border-top: none;
1178 }
1178 }
1179
1179
1180 #summary-menu-stats a {
1180 #summary-menu-stats a {
1181 display: block;
1181 display: block;
1182 padding: 12px 10px;
1182 padding: 12px 10px;
1183 background-repeat: no-repeat;
1183 background-repeat: no-repeat;
1184 background-position: 10px 50%;
1184 background-position: 10px 50%;
1185 padding-right: 10px;
1185 padding-right: 10px;
1186 }
1186 }
1187
1187
1188 #repo_size_2.loaded {
1188 #repo_size_2.loaded {
1189 margin-left: 30px;
1189 margin-left: 30px;
1190 display: block;
1190 display: block;
1191 padding-right: 10px;
1191 padding-right: 10px;
1192 padding-bottom: 7px;
1192 padding-bottom: 7px;
1193 }
1193 }
1194
1194
1195 #summary-menu-stats a:hover {
1195 #summary-menu-stats a:hover {
1196 text-decoration: none;
1196 text-decoration: none;
1197 }
1197 }
1198
1198
1199 #summary-menu-stats .badge {
1199 #summary-menu-stats .badge {
1200 padding: 2px 4px !important;
1200 padding: 2px 4px !important;
1201 font-size: 10px;
1201 font-size: 10px;
1202 }
1202 }
1203
1203
1204 #summary .metatag {
1204 #summary .metatag {
1205 display: inline-block;
1205 display: inline-block;
1206 padding: 3px 5px;
1206 padding: 3px 5px;
1207 margin-bottom: 3px;
1207 margin-bottom: 3px;
1208 margin-right: 1px;
1208 margin-right: 1px;
1209 border-radius: 5px;
1209 border-radius: 5px;
1210 }
1210 }
1211
1211
1212 #content div.panel #summary p {
1212 #content div.panel #summary p {
1213 margin-bottom: -5px;
1213 margin-bottom: -5px;
1214 width: 600px;
1214 width: 600px;
1215 white-space: pre-wrap;
1215 white-space: pre-wrap;
1216 }
1216 }
1217
1217
1218 #content div.panel #summary p:last-child {
1218 #content div.panel #summary p:last-child {
1219 margin-bottom: 9px;
1219 margin-bottom: 9px;
1220 }
1220 }
1221
1221
1222 #content div.panel #summary p:first-of-type {
1222 #content div.panel #summary p:first-of-type {
1223 margin-top: 9px;
1223 margin-top: 9px;
1224 }
1224 }
1225
1225
1226 .metatag {
1226 .metatag {
1227 display: inline-block;
1227 display: inline-block;
1228 margin-right: 1px;
1228 margin-right: 1px;
1229 border-radius: 4px 4px 4px 4px;
1229 border-radius: 4px 4px 4px 4px;
1230
1230
1231 border: solid 1px #9CF;
1231 border: solid 1px #9CF;
1232 padding: 2px 3px 2px 3px !important;
1232 padding: 2px 3px 2px 3px !important;
1233 background-color: #DEF;
1233 background-color: #DEF;
1234 }
1234 }
1235
1235
1236 .metatag[data-tag="dead"] {
1236 .metatag[data-tag="dead"] {
1237 background-color: #E44;
1237 background-color: #E44;
1238 }
1238 }
1239
1239
1240 .metatag[data-tag="stale"] {
1240 .metatag[data-tag="stale"] {
1241 background-color: #EA4;
1241 background-color: #EA4;
1242 }
1242 }
1243
1243
1244 .metatag[data-tag="featured"] {
1244 .metatag[data-tag="featured"] {
1245 background-color: #AEA;
1245 background-color: #AEA;
1246 }
1246 }
1247
1247
1248 .metatag[data-tag="requires"] {
1248 .metatag[data-tag="requires"] {
1249 background-color: #9CF;
1249 background-color: #9CF;
1250 }
1250 }
1251
1251
1252 .metatag[data-tag="recommends"] {
1252 .metatag[data-tag="recommends"] {
1253 background-color: #BDF;
1253 background-color: #BDF;
1254 }
1254 }
1255
1255
1256 .metatag[data-tag="lang"] {
1256 .metatag[data-tag="lang"] {
1257 background-color: #FAF474;
1257 background-color: #FAF474;
1258 }
1258 }
1259
1259
1260 .metatag[data-tag="license"] {
1260 .metatag[data-tag="license"] {
1261 border: solid 1px #9CF;
1261 border: solid 1px #9CF;
1262 background-color: #DEF;
1262 background-color: #DEF;
1263 }
1263 }
1264 .metatag[data-tag="see"] {
1264 .metatag[data-tag="see"] {
1265 border: solid 1px #CBD;
1265 border: solid 1px #CBD;
1266 background-color: #EDF;
1266 background-color: #EDF;
1267 }
1267 }
1268
1268
1269 a.metatag[data-tag="license"]:hover {
1269 a.metatag[data-tag="license"]:hover {
1270 background-color: #577632;
1270 background-color: #577632;
1271 color: #FFF;
1271 color: #FFF;
1272 text-decoration: none;
1272 text-decoration: none;
1273 }
1273 }
1274
1274
1275 #summary .desc {
1275 #summary .desc {
1276 white-space: pre;
1276 white-space: pre;
1277 width: 100%;
1277 width: 100%;
1278 }
1278 }
1279
1279
1280 #summary .repo_name {
1280 #summary .repo_name {
1281 font-size: 1.6em;
1281 font-size: 1.6em;
1282 font-weight: bold;
1282 font-weight: bold;
1283 vertical-align: baseline;
1283 vertical-align: baseline;
1284 clear: right
1284 clear: right
1285 }
1285 }
1286
1286
1287 #footer {
1287 #footer {
1288 clear: both;
1288 clear: both;
1289 overflow: hidden;
1289 overflow: hidden;
1290 text-align: right;
1290 text-align: right;
1291 margin: 0;
1291 margin: 0;
1292 padding: 10px 20px;
1292 padding: 10px 20px;
1293 margin: -10px 0 0;
1293 margin: -10px 0 0;
1294 background-color: #577632;
1294 background-color: #577632;
1295 background-repeat: repeat-x;
1295 background-repeat: repeat-x;
1296 background-image: linear-gradient(to bottom, #577632, #577632);
1296 background-image: linear-gradient(to bottom, #577632, #577632);
1297 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
1297 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
1298 border-radius: 4px 4px 4px 4px;
1298 border-radius: 4px 4px 4px 4px;
1299 }
1299 }
1300
1300
1301 #footer > span {
1301 #footer > span {
1302 color: #FFF;
1302 color: #FFF;
1303 font-weight: 700;
1303 font-weight: 700;
1304 }
1304 }
1305
1305
1306 #footer .navbar-link {
1306 #footer .navbar-link {
1307 color: #FFF;
1307 color: #FFF;
1308 }
1308 }
1309
1309
1310 #login div.panel-heading {
1310 #login div.panel-heading {
1311 clear: both;
1311 clear: both;
1312 overflow: hidden;
1312 overflow: hidden;
1313 position: relative;
1313 position: relative;
1314 background-color: #577632;
1314 background-color: #577632;
1315 background-repeat: repeat-x;
1315 background-repeat: repeat-x;
1316 background-image: linear-gradient(to bottom, #577632, #577632);
1316 background-image: linear-gradient(to bottom, #577632, #577632);
1317 padding: 0;
1317 padding: 0;
1318 }
1318 }
1319
1319
1320 #login .panel-body .icon-lock {
1320 #login .panel-body .icon-lock {
1321 font-size: 100px;
1321 font-size: 100px;
1322 color: #DDD;
1322 color: #DDD;
1323 position: absolute;
1323 position: absolute;
1324 margin-left: -20px;
1324 margin-left: -20px;
1325 z-index: 1;
1325 z-index: 1;
1326 }
1326 }
1327
1327
1328 #login div.inner {
1328 #login div.inner {
1329 background: #FFF;
1329 background: #FFF;
1330 border-top: none;
1330 border-top: none;
1331 border-bottom: none;
1331 border-bottom: none;
1332 margin: 0 auto;
1332 margin: 0 auto;
1333 padding: 20px;
1333 padding: 20px;
1334 }
1334 }
1335
1335
1336 #login div.form div.form-horizontal div.form-group > label {
1336 #login div.form div.form-horizontal div.form-group > label {
1337 width: 173px;
1337 width: 173px;
1338 float: left;
1338 float: left;
1339 text-align: right;
1339 text-align: right;
1340 margin: 2px 10px 0 0;
1340 margin: 2px 10px 0 0;
1341 padding: 5px 0 0 5px;
1341 padding: 5px 0 0 5px;
1342 }
1342 }
1343
1343
1344 #login div.form div.form-horizontal div.form-group div input {
1344 #login div.form div.form-horizontal div.form-group div input {
1345 background: #FFF;
1345 background: #FFF;
1346 border-top: 1px solid #b3b3b3;
1346 border-top: 1px solid #b3b3b3;
1347 border-left: 1px solid #b3b3b3;
1347 border-left: 1px solid #b3b3b3;
1348 border-right: 1px solid #eaeaea;
1348 border-right: 1px solid #eaeaea;
1349 border-bottom: 1px solid #eaeaea;
1349 border-bottom: 1px solid #eaeaea;
1350 color: #000;
1350 color: #000;
1351 font-size: 11px;
1351 font-size: 11px;
1352 margin: 0;
1352 margin: 0;
1353 padding: 7px 7px 6px;
1353 padding: 7px 7px 6px;
1354 }
1354 }
1355
1355
1356 #login div.form .buttons {
1356 #login div.form .buttons {
1357 float: right;
1357 float: right;
1358 }
1358 }
1359
1359
1360 #login div.form div.links {
1360 #login div.form div.links {
1361 clear: both;
1361 clear: both;
1362 overflow: hidden;
1362 overflow: hidden;
1363 margin: 10px 0 0;
1363 margin: 10px 0 0;
1364 border-top: 1px solid #DDD;
1364 border-top: 1px solid #DDD;
1365 padding: 10px 0 0;
1365 padding: 10px 0 0;
1366 }
1366 }
1367
1367
1368 .user-menu {
1368 .user-menu {
1369 margin: 0px !important;
1369 margin: 0px !important;
1370 float: left;
1370 float: left;
1371 }
1371 }
1372
1372
1373 .user-menu .container {
1373 .user-menu .container {
1374 padding: 0px 4px 0px 4px;
1374 padding: 0px 4px 0px 4px;
1375 margin: 0px 0px 0px 0px;
1375 margin: 0px 0px 0px 0px;
1376 }
1376 }
1377
1377
1378 .user-menu .gravatar {
1378 .user-menu .gravatar {
1379 margin: 0px 0px 0px 0px;
1379 margin: 0px 0px 0px 0px;
1380 cursor: pointer;
1380 cursor: pointer;
1381 }
1381 }
1382 .user-menu .gravatar.enabled {
1382 .user-menu .gravatar.enabled {
1383 background-color: #FDF784 !important;
1383 background-color: #FDF784 !important;
1384 }
1384 }
1385 .user-menu .gravatar:hover {
1385 .user-menu .gravatar:hover {
1386 background-color: #FDF784 !important;
1386 background-color: #FDF784 !important;
1387 }
1387 }
1388 #quick_login {
1388 #quick_login {
1389 width: 300px;
1389 width: 300px;
1390 min-height: 110px;
1390 min-height: 110px;
1391 padding: 4px;
1391 padding: 4px;
1392 position: absolute;
1392 position: absolute;
1393 right: 0;
1393 right: 0;
1394 background-color: #577632;
1394 background-color: #577632;
1395 background-repeat: repeat-x;
1395 background-repeat: repeat-x;
1396 background-image: linear-gradient(to bottom, #577632, #577632);
1396 background-image: linear-gradient(to bottom, #577632, #577632);
1397
1397
1398 z-index: 999;
1398 z-index: 999;
1399 border-radius: 0px 0px 4px 4px;
1399 border-radius: 0px 0px 4px 4px;
1400 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
1400 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
1401
1401
1402 overflow: hidden;
1402 overflow: hidden;
1403 }
1403 }
1404 #quick_login h4 {
1404 #quick_login h4 {
1405 color: #fff;
1405 color: #fff;
1406 padding: 5px 0px 5px 14px;
1406 padding: 5px 0px 5px 14px;
1407 }
1407 }
1408
1408
1409 #quick_login .password_forgoten {
1409 #quick_login .password_forgoten {
1410 padding-right: 0px;
1410 padding-right: 0px;
1411 padding-top: 0px;
1411 padding-top: 0px;
1412 text-align: left;
1412 text-align: left;
1413 }
1413 }
1414
1414
1415 #quick_login .password_forgoten a {
1415 #quick_login .password_forgoten a {
1416 font-size: 10px;
1416 font-size: 10px;
1417 color: #fff;
1417 color: #fff;
1418 padding: 0px !important;
1418 padding: 0px !important;
1419 line-height: 20px !important;
1419 line-height: 20px !important;
1420 }
1420 }
1421
1421
1422 #quick_login .register {
1422 #quick_login .register {
1423 padding-right: 10px;
1423 padding-right: 10px;
1424 padding-top: 5px;
1424 padding-top: 5px;
1425 text-align: left;
1425 text-align: left;
1426 }
1426 }
1427
1427
1428 #quick_login .register a {
1428 #quick_login .register a {
1429 font-size: 10px;
1429 font-size: 10px;
1430 color: #fff;
1430 color: #fff;
1431 padding: 0px !important;
1431 padding: 0px !important;
1432 line-height: 20px !important;
1432 line-height: 20px !important;
1433 }
1433 }
1434
1434
1435 #quick_login .submit {
1435 #quick_login .submit {
1436 margin: -20px 0 0 0px;
1436 margin: -20px 0 0 0px;
1437 position: absolute;
1437 position: absolute;
1438 right: 15px;
1438 right: 15px;
1439 }
1439 }
1440
1440
1441 #quick_login > .pull-left {
1441 #quick_login > .pull-left {
1442 width: 170px;
1442 width: 170px;
1443 }
1443 }
1444 #quick_login > .pull-right {
1444 #quick_login > .pull-right {
1445 width: 110px;
1445 width: 110px;
1446 }
1446 }
1447 #quick_login .full_name {
1447 #quick_login .full_name {
1448 color: #FFFFFF;
1448 color: #FFFFFF;
1449 font-weight: bold;
1449 font-weight: bold;
1450 padding: 3px 3px 3px 6px;
1450 padding: 3px 3px 3px 6px;
1451 }
1451 }
1452 #quick_login .big_gravatar {
1452 #quick_login .big_gravatar {
1453 padding: 4px 0px 0px 6px;
1453 padding: 4px 0px 0px 6px;
1454 }
1454 }
1455 #quick_login .notifications {
1455 #quick_login .notifications {
1456 padding: 2px 0px 0px 6px;
1456 padding: 2px 0px 0px 6px;
1457 color: #FFFFFF;
1457 color: #FFFFFF;
1458 font-weight: bold;
1458 font-weight: bold;
1459 line-height: 10px !important;
1459 line-height: 10px !important;
1460 }
1460 }
1461 #quick_login .notifications a,
1461 #quick_login .notifications a,
1462 #quick_login .unread a {
1462 #quick_login .unread a {
1463 color: #FFFFFF;
1463 color: #FFFFFF;
1464 display: block;
1464 display: block;
1465 padding: 0px !important;
1465 padding: 0px !important;
1466 }
1466 }
1467 #quick_login .notifications a:hover,
1467 #quick_login .notifications a:hover,
1468 #quick_login .unread a:hover {
1468 #quick_login .unread a:hover {
1469 background-color: inherit !important;
1469 background-color: inherit !important;
1470 }
1470 }
1471 #quick_login .email,
1471 #quick_login .email,
1472 #quick_login .unread {
1472 #quick_login .unread {
1473 color: #FFFFFF;
1473 color: #FFFFFF;
1474 padding: 3px 3px 3px 6px;
1474 padding: 3px 3px 3px 6px;
1475 }
1475 }
1476 #quick_login .links .logout {
1476 #quick_login .links .logout {
1477 }
1477 }
1478
1478
1479 #quick_login div.form div.form-horizontal {
1479 #quick_login div.form div.form-horizontal {
1480 padding-top: 2px;
1480 padding-top: 2px;
1481 padding-left: 10px;
1481 padding-left: 10px;
1482 }
1482 }
1483
1483
1484 #quick_login div.form div.form-horizontal div.form-group {
1484 #quick_login div.form div.form-horizontal div.form-group {
1485 padding: 5px;
1485 padding: 5px;
1486 }
1486 }
1487
1487
1488 #quick_login div.form div.form-horizontal div.form-group > label {
1488 #quick_login div.form div.form-horizontal div.form-group > label {
1489 color: #fff;
1489 color: #fff;
1490 padding-bottom: 3px;
1490 padding-bottom: 3px;
1491 }
1491 }
1492
1492
1493 #quick_login div.form div.form-horizontal div.form-group > div input {
1493 #quick_login div.form div.form-horizontal div.form-group > div input {
1494 width: 236px;
1494 width: 236px;
1495 background: #FFF;
1495 background: #FFF;
1496 border-top: 1px solid #b3b3b3;
1496 border-top: 1px solid #b3b3b3;
1497 border-left: 1px solid #b3b3b3;
1497 border-left: 1px solid #b3b3b3;
1498 border-right: 1px solid #eaeaea;
1498 border-right: 1px solid #eaeaea;
1499 border-bottom: 1px solid #eaeaea;
1499 border-bottom: 1px solid #eaeaea;
1500 color: #000;
1500 color: #000;
1501 font-size: 11px;
1501 font-size: 11px;
1502 margin: 0;
1502 margin: 0;
1503 padding: 5px 7px 4px;
1503 padding: 5px 7px 4px;
1504 }
1504 }
1505
1505
1506 #quick_login div.form div.form-horizontal div.buttons {
1506 #quick_login div.form div.form-horizontal div.buttons {
1507 clear: both;
1507 clear: both;
1508 overflow: hidden;
1508 overflow: hidden;
1509 text-align: right;
1509 text-align: right;
1510 margin: 0;
1510 margin: 0;
1511 padding: 5px 14px 0px 5px;
1511 padding: 5px 14px 0px 5px;
1512 }
1512 }
1513
1513
1514 #quick_login div.form div.links {
1514 #quick_login div.form div.links {
1515 clear: both;
1515 clear: both;
1516 overflow: hidden;
1516 overflow: hidden;
1517 margin: 10px 0 0;
1517 margin: 10px 0 0;
1518 padding: 0 0 2px;
1518 padding: 0 0 2px;
1519 }
1519 }
1520
1520
1521 #quick_login ol.links {
1521 #quick_login ol.links {
1522 display: block;
1522 display: block;
1523 font-weight: bold;
1523 font-weight: bold;
1524 list-style: none outside none;
1524 list-style: none outside none;
1525 text-align: right;
1525 text-align: right;
1526 }
1526 }
1527 #quick_login ol.links li {
1527 #quick_login ol.links li {
1528 line-height: 27px;
1528 line-height: 27px;
1529 margin: 0;
1529 margin: 0;
1530 padding: 0;
1530 padding: 0;
1531 color: #fff;
1531 color: #fff;
1532 display: block;
1532 display: block;
1533 float: none !important;
1533 float: none !important;
1534 }
1534 }
1535
1535
1536 #quick_login ol.links li a {
1536 #quick_login ol.links li a {
1537 color: #fff;
1537 color: #fff;
1538 display: block;
1538 display: block;
1539 padding: 2px;
1539 padding: 2px;
1540 }
1540 }
1541 #quick_login ol.links li a:HOVER {
1541 #quick_login ol.links li a:HOVER {
1542 background-color: inherit !important;
1542 background-color: inherit !important;
1543 }
1543 }
1544
1544
1545 #register div.panel-heading {
1545 #register div.panel-heading {
1546 clear: both;
1546 clear: both;
1547 overflow: hidden;
1547 overflow: hidden;
1548 position: relative;
1548 position: relative;
1549 background-color: #577632;
1549 background-color: #577632;
1550 background-repeat: repeat-x;
1550 background-repeat: repeat-x;
1551 background-image: linear-gradient(to bottom, #577632, #577632);
1551 background-image: linear-gradient(to bottom, #577632, #577632);
1552 padding: 0;
1552 padding: 0;
1553 }
1553 }
1554
1554
1555 #register div.inner {
1555 #register div.inner {
1556 background: #FFF;
1556 background: #FFF;
1557 border-top: none;
1557 border-top: none;
1558 border-bottom: none;
1558 border-bottom: none;
1559 margin: 0 auto;
1559 margin: 0 auto;
1560 padding: 20px;
1560 padding: 20px;
1561 }
1561 }
1562
1562
1563 #register div.form div.form-horizontal div.form-group > label {
1563 #register div.form div.form-horizontal div.form-group > label {
1564 width: 135px;
1564 width: 135px;
1565 float: left;
1565 float: left;
1566 text-align: right;
1566 text-align: right;
1567 margin: 2px 10px 0 0;
1567 margin: 2px 10px 0 0;
1568 padding: 5px 0 0 5px;
1568 padding: 5px 0 0 5px;
1569 }
1569 }
1570
1570
1571 #register div.form div.form-horizontal div.form-group > div input {
1571 #register div.form div.form-horizontal div.form-group > div input {
1572 width: 300px;
1572 width: 300px;
1573 background: #FFF;
1573 background: #FFF;
1574 border-top: 1px solid #b3b3b3;
1574 border-top: 1px solid #b3b3b3;
1575 border-left: 1px solid #b3b3b3;
1575 border-left: 1px solid #b3b3b3;
1576 border-right: 1px solid #eaeaea;
1576 border-right: 1px solid #eaeaea;
1577 border-bottom: 1px solid #eaeaea;
1577 border-bottom: 1px solid #eaeaea;
1578 color: #000;
1578 color: #000;
1579 font-size: 11px;
1579 font-size: 11px;
1580 margin: 0;
1580 margin: 0;
1581 padding: 7px 7px 6px;
1581 padding: 7px 7px 6px;
1582 }
1582 }
1583
1583
1584 #register div.form div.form-horizontal div.buttons {
1584 #register div.form div.form-horizontal div.buttons {
1585 clear: both;
1585 clear: both;
1586 overflow: hidden;
1586 overflow: hidden;
1587 border-top: 1px solid #DDD;
1587 border-top: 1px solid #DDD;
1588 text-align: left;
1588 text-align: left;
1589 margin: 0;
1589 margin: 0;
1590 padding: 10px 0 0 150px;
1590 padding: 10px 0 0 150px;
1591 }
1591 }
1592
1592
1593 #register div.form div.activation_msg {
1593 #register div.form div.activation_msg {
1594 padding-top: 4px;
1594 padding-top: 4px;
1595 padding-bottom: 4px;
1595 padding-bottom: 4px;
1596 }
1596 }
1597
1597
1598 #journal {
1598 #journal {
1599 margin-left: 20px;
1599 margin-left: 20px;
1600 }
1600 }
1601
1601
1602 #journal .journal_day {
1602 #journal .journal_day {
1603 font-size: 20px;
1603 font-size: 20px;
1604 padding: 10px 0px;
1604 padding: 10px 0px;
1605 border-bottom: 2px solid #DDD;
1605 border-bottom: 2px solid #DDD;
1606 margin-left: 10px;
1606 margin-left: 10px;
1607 margin-right: 10px;
1607 margin-right: 10px;
1608 }
1608 }
1609
1609
1610 #journal .journal_container {
1610 #journal .journal_container {
1611 clear: both;
1611 clear: both;
1612 }
1612 }
1613
1613
1614 #journal .journal_action_container {
1614 #journal .journal_action_container {
1615 padding-left: 18px;
1615 padding-left: 18px;
1616 }
1616 }
1617
1617
1618 #journal .journal_user {
1618 #journal .journal_user {
1619 color: #747474;
1619 color: #747474;
1620 font-size: 14px;
1620 font-size: 14px;
1621 font-weight: bold;
1621 font-weight: bold;
1622 height: 30px;
1622 height: 30px;
1623 }
1623 }
1624
1624
1625 #journal .journal_user.deleted {
1625 #journal .journal_user.deleted {
1626 color: #747474;
1626 color: #747474;
1627 font-size: 14px;
1627 font-size: 14px;
1628 font-weight: normal;
1628 font-weight: normal;
1629 height: 30px;
1629 height: 30px;
1630 font-style: italic;
1630 font-style: italic;
1631 }
1631 }
1632
1632
1633
1633
1634 #journal .journal_icon {
1634 #journal .journal_icon {
1635 clear: both;
1635 clear: both;
1636 float: left;
1636 float: left;
1637 padding-right: 4px;
1637 padding-right: 4px;
1638 padding-top: 3px;
1638 padding-top: 3px;
1639 }
1639 }
1640
1640
1641 #journal .journal_action {
1641 #journal .journal_action {
1642 padding-top: 4px;
1642 padding-top: 4px;
1643 min-height: 2px;
1643 min-height: 2px;
1644 float: left
1644 float: left
1645 }
1645 }
1646
1646
1647 #journal .journal_action_params {
1647 #journal .journal_action_params {
1648 clear: left;
1648 clear: left;
1649 padding-left: 22px;
1649 padding-left: 22px;
1650 }
1650 }
1651
1651
1652 #journal .journal_repo {
1652 #journal .journal_repo {
1653 float: left;
1653 float: left;
1654 margin-left: 6px;
1654 margin-left: 6px;
1655 padding-top: 3px;
1655 padding-top: 3px;
1656 }
1656 }
1657
1657
1658 #journal .date {
1658 #journal .date {
1659 clear: both;
1659 clear: both;
1660 color: #777777;
1660 color: #777777;
1661 font-size: 11px;
1661 font-size: 11px;
1662 padding-left: 22px;
1662 padding-left: 22px;
1663 }
1663 }
1664
1664
1665 #journal .journal_repo .journal_repo_name {
1665 #journal .journal_repo .journal_repo_name {
1666 font-weight: bold;
1666 font-weight: bold;
1667 font-size: 1.1em;
1667 font-size: 1.1em;
1668 }
1668 }
1669
1669
1670 #journal .compare_view {
1670 #journal .compare_view {
1671 padding: 5px 0px 5px 0px;
1671 padding: 5px 0px 5px 0px;
1672 width: 95px;
1672 width: 95px;
1673 }
1673 }
1674
1674
1675 .trending_language_tbl, .trending_language_tbl td {
1675 .trending_language_tbl, .trending_language_tbl td {
1676 border: 0 !important;
1676 border: 0 !important;
1677 margin: 0 !important;
1677 margin: 0 !important;
1678 padding: 0 !important;
1678 padding: 0 !important;
1679 }
1679 }
1680
1680
1681 .trending_language_tbl, .trending_language_tbl tr {
1681 .trending_language_tbl, .trending_language_tbl tr {
1682 border-spacing: 1px;
1682 border-spacing: 1px;
1683 }
1683 }
1684
1684
1685 #lang_stats .progress-bar {
1685 #lang_stats .progress-bar {
1686 background-color: #577632;
1686 background-color: #577632;
1687 color: #FFF;
1687 color: #FFF;
1688 display: block;
1688 display: block;
1689 min-width: 20px;
1689 min-width: 20px;
1690 text-decoration: none;
1690 text-decoration: none;
1691 height: 12px;
1691 height: 12px;
1692 margin-bottom: 0px;
1692 margin-bottom: 0px;
1693 margin-left: 5px;
1693 margin-left: 5px;
1694 white-space: pre;
1694 white-space: pre;
1695 padding: 3px;
1695 padding: 3px;
1696 border-top-right-radius: 8px;
1696 border-top-right-radius: 8px;
1697 border-bottom-right-radius: 8px;
1697 border-bottom-right-radius: 8px;
1698 }
1698 }
1699
1699
1700 #lang_stats table td {
1700 #lang_stats table td {
1701 border-bottom: none !important;
1701 border-bottom: none !important;
1702 padding: 1px 0 !important;
1702 padding: 1px 0 !important;
1703 }
1703 }
1704
1704
1705 h3.files_location {
1705 h3.files_location {
1706 font-size: 1.8em;
1706 font-size: 1.8em;
1707 font-weight: 700;
1707 font-weight: 700;
1708 border-bottom: none !important;
1708 border-bottom: none !important;
1709 margin: 10px 0 !important;
1709 margin: 10px 0 !important;
1710 }
1710 }
1711
1711
1712 #files_data dl dt {
1712 #files_data dl dt {
1713 float: left;
1713 float: left;
1714 width: 60px;
1714 width: 60px;
1715 margin: 0 !important;
1715 margin: 0 !important;
1716 padding: 5px;
1716 padding: 5px;
1717 }
1717 }
1718
1718
1719 #files_data dl dd {
1719 #files_data dl dd {
1720 margin: 0 !important;
1720 margin: 0 !important;
1721 padding: 5px !important;
1721 padding: 5px !important;
1722 }
1722 }
1723
1723
1724 #files_data .codeblock #editor_container .error-message {
1724 #files_data .codeblock #editor_container .error-message {
1725 color: red;
1725 color: red;
1726 padding: 10px 10px 10px 26px
1726 padding: 10px 10px 10px 26px
1727 }
1727 }
1728
1728
1729 .file_history {
1729 .file_history {
1730 padding-top: 10px;
1730 padding-top: 10px;
1731 font-size: 16px;
1731 font-size: 16px;
1732 }
1732 }
1733 .file_author {
1733 .file_author {
1734 float: left;
1734 float: left;
1735 }
1735 }
1736
1736
1737 .file_author .item {
1737 .file_author .item {
1738 float: left;
1738 float: left;
1739 padding: 5px;
1739 padding: 5px;
1740 color: #888;
1740 color: #888;
1741 }
1741 }
1742
1742
1743 .changeset_id {
1743 .changeset_id {
1744 color: #666666;
1744 color: #666666;
1745 margin-right: -3px;
1745 margin-right: -3px;
1746 }
1746 }
1747
1747
1748 .changeset-logical-index {
1748 .changeset-logical-index {
1749 color: #666666;
1749 color: #666666;
1750 font-style: italic;
1750 font-style: italic;
1751 font-size: 85%;
1751 font-size: 85%;
1752 padding-right: 0.5em;
1752 padding-right: 0.5em;
1753 text-align: right;
1753 text-align: right;
1754 }
1754 }
1755
1755
1756 #changeset_content {
1756 #changeset_content {
1757 border-left: 1px solid #CCC;
1757 border-left: 1px solid #CCC;
1758 border-right: 1px solid #CCC;
1758 border-right: 1px solid #CCC;
1759 border-bottom: 1px solid #CCC;
1759 border-bottom: 1px solid #CCC;
1760 padding: 5px;
1760 padding: 5px;
1761 }
1761 }
1762
1762
1763 #changeset_compare_view_content {
1763 #changeset_compare_view_content {
1764 border: 1px solid #CCC;
1764 border: 1px solid #CCC;
1765 padding: 5px;
1765 padding: 5px;
1766 }
1766 }
1767
1767
1768 #changeset_content .container {
1768 #changeset_content .container {
1769 font-size: 1.2em;
1769 font-size: 1.2em;
1770 overflow: hidden;
1770 overflow: hidden;
1771 }
1771 }
1772
1772
1773 #changeset_compare_view_content .compare_view_commits {
1773 #changeset_compare_view_content .compare_view_commits {
1774 width: auto !important;
1774 width: auto !important;
1775 }
1775 }
1776
1776
1777 #changeset_compare_view_content .compare_view_commits td {
1777 #changeset_compare_view_content .compare_view_commits td {
1778 padding: 0px 0px 0px 12px !important;
1778 padding: 0px 0px 0px 12px !important;
1779 }
1779 }
1780
1780
1781 #changeset_content .container .right {
1781 #changeset_content .container .right {
1782 float: right;
1782 float: right;
1783 width: 20%;
1783 width: 20%;
1784 text-align: right;
1784 text-align: right;
1785 }
1785 }
1786
1786
1787 #changeset_content .container .message {
1787 #changeset_content .container .message {
1788 white-space: pre-wrap;
1788 white-space: pre-wrap;
1789 }
1789 }
1790 #changeset_content .container .message a:hover {
1790 #changeset_content .container .message a:hover {
1791 text-decoration: none;
1791 text-decoration: none;
1792 }
1792 }
1793 .cs_files .cur_cs {
1793 .cs_files .cur_cs {
1794 margin: 10px 2px;
1794 margin: 10px 2px;
1795 font-weight: bold;
1795 font-weight: bold;
1796 }
1796 }
1797
1797
1798 .cs_files .node {
1798 .cs_files .node {
1799 float: left;
1799 float: left;
1800 }
1800 }
1801
1801
1802 .cs_files .changes {
1802 .cs_files .changes {
1803 float: right;
1803 float: right;
1804 color: #577632;
1804 color: #577632;
1805 }
1805 }
1806
1806
1807 .cs_files .changes .added {
1807 .cs_files .changes .added {
1808 background-color: #BBFFBB;
1808 background-color: #BBFFBB;
1809 float: left;
1809 float: left;
1810 text-align: center;
1810 text-align: center;
1811 font-size: 9px;
1811 font-size: 9px;
1812 padding: 2px 0px 2px 0px;
1812 padding: 2px 0px 2px 0px;
1813 }
1813 }
1814
1814
1815 .cs_files .changes .deleted {
1815 .cs_files .changes .deleted {
1816 background-color: #FF8888;
1816 background-color: #FF8888;
1817 float: left;
1817 float: left;
1818 text-align: center;
1818 text-align: center;
1819 font-size: 9px;
1819 font-size: 9px;
1820 padding: 2px 0px 2px 0px;
1820 padding: 2px 0px 2px 0px;
1821 }
1821 }
1822 /*new binary
1822 /*new binary
1823 NEW_FILENODE = 1
1823 NEW_FILENODE = 1
1824 DEL_FILENODE = 2
1824 DEL_FILENODE = 2
1825 MOD_FILENODE = 3
1825 MOD_FILENODE = 3
1826 RENAMED_FILENODE = 4
1826 RENAMED_FILENODE = 4
1827 CHMOD_FILENODE = 5
1827 CHMOD_FILENODE = 5
1828 BIN_FILENODE = 6
1828 BIN_FILENODE = 6
1829 */
1829 */
1830 .cs_files .changes .bin {
1830 .cs_files .changes .bin {
1831 background-color: #BBFFBB;
1831 background-color: #BBFFBB;
1832 float: left;
1832 float: left;
1833 text-align: center;
1833 text-align: center;
1834 font-size: 9px;
1834 font-size: 9px;
1835 padding: 2px 0px 2px 0px;
1835 padding: 2px 0px 2px 0px;
1836 }
1836 }
1837 .cs_files .changes .bin.bin1 {
1837 .cs_files .changes .bin.bin1 {
1838 background-color: #BBFFBB;
1838 background-color: #BBFFBB;
1839 }
1839 }
1840
1840
1841 /*deleted binary*/
1841 /*deleted binary*/
1842 .cs_files .changes .bin.bin2 {
1842 .cs_files .changes .bin.bin2 {
1843 background-color: #FF8888;
1843 background-color: #FF8888;
1844 }
1844 }
1845
1845
1846 /*mod binary*/
1846 /*mod binary*/
1847 .cs_files .changes .bin.bin3 {
1847 .cs_files .changes .bin.bin3 {
1848 background-color: #DDDDDD;
1848 background-color: #DDDDDD;
1849 }
1849 }
1850
1850
1851 /*rename file*/
1851 /*rename file*/
1852 .cs_files .changes .bin.bin4 {
1852 .cs_files .changes .bin.bin4 {
1853 background-color: #6D99FF;
1853 background-color: #6D99FF;
1854 }
1854 }
1855
1855
1856 /*rename file*/
1856 /*rename file*/
1857 .cs_files .changes .bin.bin4 {
1857 .cs_files .changes .bin.bin4 {
1858 background-color: #6D99FF;
1858 background-color: #6D99FF;
1859 }
1859 }
1860
1860
1861 /*chmod file*/
1861 /*chmod file*/
1862 .cs_files .changes .bin.bin5 {
1862 .cs_files .changes .bin.bin5 {
1863 background-color: #6D99FF;
1863 background-color: #6D99FF;
1864 }
1864 }
1865
1865
1866 .cs_files .cs_added,
1866 .cs_files .cs_added,
1867 .cs_files .cs_A {
1867 .cs_files .cs_A {
1868 height: 16px;
1868 height: 16px;
1869 margin-top: 7px;
1869 margin-top: 7px;
1870 text-align: left;
1870 text-align: left;
1871 }
1871 }
1872
1872
1873 .cs_files .cs_changed,
1873 .cs_files .cs_changed,
1874 .cs_files .cs_M {
1874 .cs_files .cs_M {
1875 height: 16px;
1875 height: 16px;
1876 margin-top: 7px;
1876 margin-top: 7px;
1877 text-align: left;
1877 text-align: left;
1878 }
1878 }
1879
1879
1880 .cs_files .cs_removed,
1880 .cs_files .cs_removed,
1881 .cs_files .cs_D {
1881 .cs_files .cs_D {
1882 height: 16px;
1882 height: 16px;
1883 margin-top: 7px;
1883 margin-top: 7px;
1884 text-align: left;
1884 text-align: left;
1885 }
1885 }
1886
1886
1887 .cs_files .cs_renamed,
1887 .cs_files .cs_renamed,
1888 .cs_files .cs_R {
1888 .cs_files .cs_R {
1889 height: 16px;
1889 height: 16px;
1890 margin-top: 7px;
1890 margin-top: 7px;
1891 text-align: left;
1891 text-align: left;
1892 }
1892 }
1893
1893
1894 #graph {
1894 #graph {
1895 position: relative;
1895 position: relative;
1896 overflow: hidden;
1896 overflow: hidden;
1897 }
1897 }
1898
1898
1899 #graph_nodes {
1899 #graph_nodes {
1900 position: absolute;
1900 position: absolute;
1901 width: 100px;
1901 width: 100px;
1902 }
1902 }
1903
1903
1904 #graph_content,
1904 #graph_content,
1905 #graph .info_box,
1905 #graph .info_box,
1906 #graph .container_header {
1906 #graph .container_header {
1907 margin-left: 100px;
1907 margin-left: 100px;
1908 }
1908 }
1909
1909
1910 #graph_content {
1910 #graph_content {
1911 position: relative;
1911 position: relative;
1912 }
1912 }
1913
1913
1914 #graph .container_header {
1914 #graph .container_header {
1915 padding: 10px;
1915 padding: 10px;
1916 height: 25px;
1916 height: 25px;
1917 }
1917 }
1918
1918
1919 #graph_content #rev_range_container {
1919 #graph_content #rev_range_container {
1920 float: left;
1920 float: left;
1921 margin: 0px 0px 0px 3px;
1921 margin: 0px 0px 0px 3px;
1922 }
1922 }
1923
1923
1924 #graph_content #rev_range_clear {
1924 #graph_content #rev_range_clear {
1925 float: left;
1925 float: left;
1926 margin: 0px 0px 0px 3px;
1926 margin: 0px 0px 0px 3px;
1927 }
1927 }
1928
1928
1929 #graph_content #changesets {
1929 #graph_content #changesets {
1930 table-layout: fixed;
1930 table-layout: fixed;
1931 border-collapse: collapse;
1931 border-collapse: collapse;
1932 border-left: none;
1932 border-left: none;
1933 border-right: none;
1933 border-right: none;
1934 border-color: #cdcdcd;
1934 border-color: #cdcdcd;
1935 }
1935 }
1936
1936
1937 #updaterevs-table tr.mergerow,
1937 #updaterevs-table tr.mergerow,
1938 #graph_content_pr tr.mergerow,
1938 #graph_content_pr tr.mergerow,
1939 #shortlog_data tr.mergerow,
1939 #shortlog_data tr.mergerow,
1940 #graph_content #changesets tr.out-of-range,
1940 #graph_content #changesets tr.out-of-range,
1941 #graph_content #changesets tr.mergerow {
1941 #graph_content #changesets tr.mergerow {
1942 opacity: 0.6;
1942 opacity: 0.6;
1943 }
1943 }
1944
1944
1945 #graph_content #changesets td {
1945 #graph_content #changesets td {
1946 overflow: hidden;
1946 overflow: hidden;
1947 text-overflow: ellipsis;
1947 text-overflow: ellipsis;
1948 white-space: nowrap;
1948 white-space: nowrap;
1949 height: 31px;
1949 height: 31px;
1950 border-color: #cdcdcd;
1950 border-color: #cdcdcd;
1951 text-align: left;
1951 text-align: left;
1952 }
1952 }
1953
1953
1954 #graph_content .container .checkbox {
1954 #graph_content .container .checkbox {
1955 width: 14px;
1955 width: 14px;
1956 font-size: 0.85em;
1956 font-size: 0.85em;
1957 }
1957 }
1958
1958
1959 #graph_content .container .status {
1959 #graph_content .container .status {
1960 width: 14px;
1960 width: 14px;
1961 font-size: 0.85em;
1961 font-size: 0.85em;
1962 }
1962 }
1963
1963
1964 #graph_content .container .author {
1964 #graph_content .container .author {
1965 width: 105px;
1965 width: 105px;
1966 }
1966 }
1967
1967
1968 #graph_content .container .hash {
1968 #graph_content .container .hash {
1969 width: 100px;
1969 width: 100px;
1970 font-size: 0.85em;
1970 font-size: 0.85em;
1971 }
1971 }
1972
1972
1973 #graph_content #changesets .container .date {
1973 #graph_content #changesets .container .date {
1974 width: 76px;
1974 width: 76px;
1975 color: #666;
1975 color: #666;
1976 font-size: 10px;
1976 font-size: 10px;
1977 }
1977 }
1978
1978
1979 #graph_content_pr .compare_view_commits .expand_commit,
1979 #graph_content_pr .compare_view_commits .expand_commit,
1980 #graph_content .container .expand_commit {
1980 #graph_content .container .expand_commit {
1981 width: 24px;
1981 width: 24px;
1982 cursor: pointer;
1982 cursor: pointer;
1983 }
1983 }
1984
1984
1985 #graph_content #changesets .container .right {
1985 #graph_content #changesets .container .right {
1986 width: 120px;
1986 width: 120px;
1987 padding-right: 0px;
1987 padding-right: 0px;
1988 overflow: visible;
1988 overflow: visible;
1989 position: relative;
1989 position: relative;
1990 }
1990 }
1991
1991
1992 #graph_content .container .mid {
1992 #graph_content .container .mid {
1993 padding: 0;
1993 padding: 0;
1994 }
1994 }
1995
1995
1996 #graph_content .log-container {
1996 #graph_content .log-container {
1997 position: relative;
1997 position: relative;
1998 }
1998 }
1999
1999
2000 #graph_content .container #singlerange,
2000 #graph_content .container #singlerange,
2001 #graph_content .container .changeset_range {
2001 #graph_content .container .changeset_range {
2002 float: left;
2002 float: left;
2003 margin: 6px 3px;
2003 margin: 6px 3px;
2004 }
2004 }
2005
2005
2006 #graph_content .container .author img {
2006 #graph_content .container .author img {
2007 vertical-align: middle;
2007 vertical-align: middle;
2008 }
2008 }
2009
2009
2010 #graph_content .container .author .user {
2010 #graph_content .container .author .user {
2011 color: #444444;
2011 color: #444444;
2012 }
2012 }
2013
2013
2014 #graph_content .container .mid .message {
2014 #graph_content .container .mid .message {
2015 white-space: pre-wrap;
2015 white-space: pre-wrap;
2016 padding: 0;
2016 padding: 0;
2017 overflow: hidden;
2017 overflow: hidden;
2018 height: 1.1em;
2018 height: 1.1em;
2019 }
2019 }
2020
2020
2021 #graph_content_pr .compare_view_commits .message {
2021 #graph_content_pr .compare_view_commits .message {
2022 padding: 0 !important;
2022 padding: 0 !important;
2023 height: 1.1em;
2023 height: 1.1em;
2024 }
2024 }
2025
2025
2026 #graph_content .container .mid .message.expanded,
2026 #graph_content .container .mid .message.expanded,
2027 #graph_content_pr .compare_view_commits .message.expanded {
2027 #graph_content_pr .compare_view_commits .message.expanded {
2028 height: auto;
2028 height: auto;
2029 margin: 8px 0px 8px 0px;
2029 margin: 8px 0px 8px 0px;
2030 overflow: initial;
2030 overflow: initial;
2031 }
2031 }
2032
2032
2033 #graph_content .container .extra-container {
2033 #graph_content .container .extra-container {
2034 display: block;
2034 display: block;
2035 position: absolute;
2035 position: absolute;
2036 top: -15px;
2036 top: -15px;
2037 right: 0;
2037 right: 0;
2038 padding-left: 5px;
2038 padding-left: 5px;
2039 background: #FFFFFF;
2039 background: #FFFFFF;
2040 height: 41px;
2040 height: 41px;
2041 }
2041 }
2042
2042
2043 #pull_request_overview .comments-container,
2043 #pull_request_overview .comments-container,
2044 #changeset_compare_view_content .comments-container,
2044 #changeset_compare_view_content .comments-container,
2045 #graph_content .comments-container,
2045 #graph_content .comments-container,
2046 #shortlog_data .comments-container,
2046 #shortlog_data .comments-container,
2047 #graph_content .logtags {
2047 #graph_content .logtags {
2048 display: block;
2048 display: block;
2049 float: left;
2049 float: left;
2050 overflow: hidden;
2050 overflow: hidden;
2051 padding: 0;
2051 padding: 0;
2052 margin: 0;
2052 margin: 0;
2053 white-space: nowrap;
2053 white-space: nowrap;
2054 }
2054 }
2055
2055
2056 #graph_content .comments-container {
2056 #graph_content .comments-container {
2057 margin: 0.8em 0;
2057 margin: 0.8em 0;
2058 margin-right: 0.5em;
2058 margin-right: 0.5em;
2059 }
2059 }
2060
2060
2061 #graph_content .tagcontainer {
2061 #graph_content .tagcontainer {
2062 width: 80px;
2062 width: 80px;
2063 position: relative;
2063 position: relative;
2064 float: right;
2064 float: right;
2065 height: 100%;
2065 height: 100%;
2066 top: 7px;
2066 top: 7px;
2067 margin-left: 0.5em;
2067 margin-left: 0.5em;
2068 }
2068 }
2069
2069
2070 #graph_content .logtags {
2070 #graph_content .logtags {
2071 min-width: 80px;
2071 min-width: 80px;
2072 height: 1.1em;
2072 height: 1.1em;
2073 position: absolute;
2073 position: absolute;
2074 left: 0px;
2074 left: 0px;
2075 width: auto;
2075 width: auto;
2076 top: 0px;
2076 top: 0px;
2077 }
2077 }
2078
2078
2079 #graph_content .logtags.tags {
2079 #graph_content .logtags.tags {
2080 top: 14px;
2080 top: 14px;
2081 }
2081 }
2082
2082
2083 #graph_content .logtags:hover {
2083 #graph_content .logtags:hover {
2084 overflow: visible;
2084 overflow: visible;
2085 position: absolute;
2085 position: absolute;
2086 width: auto;
2086 width: auto;
2087 right: 0;
2087 right: 0;
2088 left: initial;
2088 left: initial;
2089 }
2089 }
2090
2090
2091 #graph_content .logtags .booktag,
2091 #graph_content .logtags .booktag,
2092 #graph_content .logtags .tagtag {
2092 #graph_content .logtags .tagtag {
2093 float: left;
2093 float: left;
2094 line-height: 1em;
2094 line-height: 1em;
2095 margin-bottom: 1px;
2095 margin-bottom: 1px;
2096 margin-right: 1px;
2096 margin-right: 1px;
2097 padding: 1px 3px;
2097 padding: 1px 3px;
2098 font-size: 10px;
2098 font-size: 10px;
2099 }
2099 }
2100
2100
2101 #graph_content .container .mid .message a:hover {
2101 #graph_content .container .mid .message a:hover {
2102 text-decoration: none;
2102 text-decoration: none;
2103 }
2103 }
2104
2104
2105 #compare_branches + div.panel-body .revision-link,
2105 #compare_branches + div.panel-body .revision-link,
2106 #compare_tags + div.panel-body .revision-link,
2106 #compare_tags + div.panel-body .revision-link,
2107 #compare_bookmarks + div.panel-body .revision-link,
2107 #compare_bookmarks + div.panel-body .revision-link,
2108 div.panel-body #files_data .revision-link,
2108 div.panel-body #files_data .revision-link,
2109 #repos_list_wrap .revision-link,
2109 #repos_list_wrap .revision-link,
2110 #shortlog_data .revision-link {
2110 #shortlog_data .revision-link {
2111 font-weight: normal !important;
2111 font-weight: normal !important;
2112 font-family: monospace;
2112 font-family: monospace;
2113 font-size: 12px;
2113 font-size: 12px;
2114 color: #577632;
2114 color: #577632;
2115 }
2115 }
2116
2116
2117 .revision-link {
2117 .revision-link {
2118 color: #3F6F9F;
2118 color: #3F6F9F;
2119 font-weight: bold !important;
2119 font-weight: bold !important;
2120 }
2120 }
2121
2121
2122 .issue-tracker-link {
2122 .issue-tracker-link {
2123 color: #3F6F9F;
2123 color: #3F6F9F;
2124 font-weight: bold !important;
2124 font-weight: bold !important;
2125 }
2125 }
2126
2126
2127 .changeset-status-container {
2127 .changeset-status-container {
2128 padding-right: 5px;
2128 padding-right: 5px;
2129 margin-top: 1px;
2129 margin-top: 1px;
2130 float: right;
2130 float: right;
2131 height: 14px;
2131 height: 14px;
2132 }
2132 }
2133 .code-header .changeset-status-container {
2133 .code-header .changeset-status-container {
2134 float: left;
2134 float: left;
2135 padding: 2px 0px 0px 2px;
2135 padding: 2px 0px 0px 2px;
2136 }
2136 }
2137 .code-header .changeset-status-container .changeset-status-lbl {
2137 .code-header .changeset-status-container .changeset-status-lbl {
2138 float: left;
2138 float: left;
2139 padding: 0px 4px 0px 0px;
2139 padding: 0px 4px 0px 0px;
2140 }
2140 }
2141 .changeset-status-container div.changeset-status-ico {
2141 .changeset-status-container div.changeset-status-ico {
2142 float: left;
2142 float: left;
2143 }
2143 }
2144 .code-header .changeset-status-container .changeset-status-ico,
2144 .code-header .changeset-status-container .changeset-status-ico,
2145 .container .changeset-status-ico {
2145 .container .changeset-status-ico {
2146 float: left;
2146 float: left;
2147 }
2147 }
2148
2148
2149 /* changeset statuses (must be the same name as the status) */
2149 /* changeset statuses (must be the same name as the status) */
2150 .changeset-status-not_reviewed {
2150 .changeset-status-not_reviewed {
2151 color: #bababa;
2151 color: #bababa;
2152 }
2152 }
2153 .changeset-status-approved {
2153 .changeset-status-approved {
2154 color: #81ba51;
2154 color: #81ba51;
2155 }
2155 }
2156 .changeset-status-rejected {
2156 .changeset-status-rejected {
2157 color: #d06060;
2157 color: #d06060;
2158 }
2158 }
2159 .changeset-status-under_review {
2159 .changeset-status-under_review {
2160 color: #ffc71e;
2160 color: #ffc71e;
2161 }
2161 }
2162
2162
2163 #graph_content .comments-cnt {
2163 #graph_content .comments-cnt {
2164 color: rgb(136, 136, 136);
2164 color: rgb(136, 136, 136);
2165 padding: 5px 0;
2165 padding: 5px 0;
2166 }
2166 }
2167
2167
2168 #shortlog_data .comments-cnt {
2168 #shortlog_data .comments-cnt {
2169 color: rgb(136, 136, 136);
2169 color: rgb(136, 136, 136);
2170 padding: 3px 0;
2170 padding: 3px 0;
2171 }
2171 }
2172
2172
2173 .right .changes {
2173 .right .changes {
2174 clear: both;
2174 clear: both;
2175 }
2175 }
2176
2176
2177 .right .changes .changed_total {
2177 .right .changes .changed_total {
2178 display: block;
2178 display: block;
2179 float: right;
2179 float: right;
2180 text-align: center;
2180 text-align: center;
2181 min-width: 45px;
2181 min-width: 45px;
2182 cursor: pointer;
2182 cursor: pointer;
2183 color: #444444;
2183 color: #444444;
2184 background: #FEA;
2184 background: #FEA;
2185 border-radius: 0px 0px 0px 6px;
2185 border-radius: 0px 0px 0px 6px;
2186 padding: 1px;
2186 padding: 1px;
2187 }
2187 }
2188
2188
2189 .right .changes .added,
2189 .right .changes .added,
2190 .changed, .removed {
2190 .changed, .removed {
2191 display: block;
2191 display: block;
2192 padding: 1px;
2192 padding: 1px;
2193 color: #444444;
2193 color: #444444;
2194 float: right;
2194 float: right;
2195 text-align: center;
2195 text-align: center;
2196 min-width: 15px;
2196 min-width: 15px;
2197 }
2197 }
2198
2198
2199 .right .changes .added {
2199 .right .changes .added {
2200 background: #CFC;
2200 background: #CFC;
2201 }
2201 }
2202
2202
2203 .right .changes .changed {
2203 .right .changes .changed {
2204 background: #FEA;
2204 background: #FEA;
2205 }
2205 }
2206
2206
2207 .right .changes .removed {
2207 .right .changes .removed {
2208 background: #FAA;
2208 background: #FAA;
2209 }
2209 }
2210
2210
2211 .right .mergetag,
2211 .right .mergetag,
2212 .right .merge {
2212 .right .merge {
2213 padding: 1px 3px 1px 3px;
2213 padding: 1px 3px 1px 3px;
2214 background-color: #fca062;
2214 background-color: #fca062;
2215 font-size: 10px;
2215 font-size: 10px;
2216 color: #ffffff;
2216 color: #ffffff;
2217 text-transform: uppercase;
2217 text-transform: uppercase;
2218 white-space: nowrap;
2218 white-space: nowrap;
2219 border-radius: 3px;
2219 border-radius: 3px;
2220 margin-right: 2px;
2220 margin-right: 2px;
2221 }
2221 }
2222
2222
2223 .right .parent {
2223 .right .parent {
2224 color: #666666;
2224 color: #666666;
2225 clear: both;
2225 clear: both;
2226 }
2226 }
2227 .right .logtags {
2227 .right .logtags {
2228 line-height: 2.2em;
2228 line-height: 2.2em;
2229 }
2229 }
2230 .phasetag, .bumpedtag, .divergenttag, .extincttag, .unstabletag, .repotag, .branchtag, .logtags .tagtag, .logtags .booktag {
2230 .phasetag, .bumpedtag, .divergenttag, .extincttag, .unstabletag, .repotag, .branchtag, .logtags .tagtag, .logtags .booktag {
2231 margin: 0px 2px;
2231 margin: 0px 2px;
2232 }
2232 }
2233
2233
2234 .phasetag,
2234 .phasetag,
2235 .bumpedtag,
2235 .bumpedtag,
2236 .divergenttag,
2236 .divergenttag,
2237 .extincttag,
2237 .extincttag,
2238 .unstabletag,
2238 .unstabletag,
2239 .repotag,
2239 .repotag,
2240 .branchtag,
2240 .branchtag,
2241 .tagtag,
2241 .tagtag,
2242 .booktag,
2242 .booktag,
2243 .spantag {
2243 .spantag {
2244 padding: 1px 3px 1px 3px;
2244 padding: 1px 3px 1px 3px;
2245 font-size: 10px;
2245 font-size: 10px;
2246 color: #577632;
2246 color: #577632;
2247 white-space: nowrap;
2247 white-space: nowrap;
2248 border-radius: 4px;
2248 border-radius: 4px;
2249 border: 1px solid #d9e8f8;
2249 border: 1px solid #d9e8f8;
2250 line-height: 1.5em;
2250 line-height: 1.5em;
2251 }
2251 }
2252
2252
2253 #graph_content .phasetag,
2253 #graph_content .phasetag,
2254 #graph_content .bumpedtag,
2254 #graph_content .bumpedtag,
2255 #graph_content .divergenttag,
2255 #graph_content .divergenttag,
2256 #graph_content .extincttag,
2256 #graph_content .extincttag,
2257 #graph_content .unstabletag,
2257 #graph_content .unstabletag,
2258 #graph_content .branchtag,
2258 #graph_content .branchtag,
2259 #graph_content .tagtag,
2259 #graph_content .tagtag,
2260 #graph_content .booktag {
2260 #graph_content .booktag {
2261 margin: 1.1em 0;
2261 margin: 1.1em 0;
2262 margin-right: 0.5em;
2262 margin-right: 0.5em;
2263 }
2263 }
2264
2264
2265 .phasetag,
2265 .phasetag,
2266 .bumpedtag,
2266 .bumpedtag,
2267 .divergenttag,
2267 .divergenttag,
2268 .extincttag,
2268 .extincttag,
2269 .unstabletag,
2269 .unstabletag,
2270 .repotag,
2270 .repotag,
2271 .branchtag,
2271 .branchtag,
2272 .tagtag,
2272 .tagtag,
2273 .booktag {
2273 .booktag {
2274 float: left;
2274 float: left;
2275 display: inline-block;
2275 display: inline-block;
2276 }
2276 }
2277
2277
2278 .right .logtags .phasetag,
2278 .right .logtags .phasetag,
2279 .right .logtags .bumpedtag,
2279 .right .logtags .bumpedtag,
2280 .right .logtags .divergenttag,
2280 .right .logtags .divergenttag,
2281 .right .logtags .extincttag,
2281 .right .logtags .extincttag,
2282 .right .logtags .unstabletag,
2282 .right .logtags .unstabletag,
2283 .right .logtags .branchtag,
2283 .right .logtags .branchtag,
2284 .right .logtags .tagtag,
2284 .right .logtags .tagtag,
2285 .right .logtags .booktag,
2285 .right .logtags .booktag,
2286 .right .mergetag,
2286 .right .mergetag,
2287 .right .merge {
2287 .right .merge {
2288 float: right;
2288 float: right;
2289 line-height: 1em;
2289 line-height: 1em;
2290 margin: 1px 1px !important;
2290 margin: 1px 1px !important;
2291 display: block;
2291 display: block;
2292 }
2292 }
2293
2293
2294 .repotag {
2294 .repotag {
2295 border-color: #56A546;
2295 border-color: #56A546;
2296 color: #46A546;
2296 color: #46A546;
2297 font-size: 8px;
2297 font-size: 8px;
2298 text-transform: uppercase;
2298 text-transform: uppercase;
2299 }
2299 }
2300
2300
2301 #context-bar .repotag,
2301 #context-bar .repotag,
2302 .repo-icons .repotag {
2302 .repo-icons .repotag {
2303 border-color: white;
2303 border-color: white;
2304 color: white;
2304 color: white;
2305 margin-top: 3px;
2305 margin-top: 3px;
2306 }
2306 }
2307
2307
2308 .repo-icons .repotag {
2308 .repo-icons .repotag {
2309 margin-top: 0px;
2309 margin-top: 0px;
2310 padding-top: 0px;
2310 padding-top: 0px;
2311 padding-bottom: 0px;
2311 padding-bottom: 0px;
2312 }
2312 }
2313
2313
2314 .booktag {
2314 .booktag {
2315 border-color: #46A546;
2315 border-color: #46A546;
2316 color: #46A546;
2316 color: #46A546;
2317 }
2317 }
2318
2318
2319 .tagtag {
2319 .tagtag {
2320 border-color: #62cffc;
2320 border-color: #62cffc;
2321 color: #62cffc;
2321 color: #62cffc;
2322 }
2322 }
2323
2323
2324 .bumpedtag,
2324 .bumpedtag,
2325 .divergenttag,
2325 .divergenttag,
2326 .extincttag,
2326 .extincttag,
2327 .unstabletag {
2327 .unstabletag {
2328 background-color: #f00;
2328 background-color: #f00;
2329 border-color: #600;
2329 border-color: #600;
2330 color: #fff;
2330 color: #fff;
2331 }
2331 }
2332
2332
2333 .phasetag {
2333 .phasetag {
2334 border-color: #1F14CE;
2334 border-color: #1F14CE;
2335 color: #1F14CE;
2335 color: #1F14CE;
2336 }
2336 }
2337
2337
2338 .logtags .branchtag a:hover,
2338 .logtags .branchtag a:hover,
2339 .logtags .branchtag a,
2339 .logtags .branchtag a,
2340 .branchtag a,
2340 .branchtag a,
2341 .branchtag a:hover {
2341 .branchtag a:hover {
2342 text-decoration: none;
2342 text-decoration: none;
2343 color: inherit;
2343 color: inherit;
2344 }
2344 }
2345 .logtags .tagtag {
2345 .logtags .tagtag {
2346 padding: 1px 3px 1px 3px;
2346 padding: 1px 3px 1px 3px;
2347 background-color: #62cffc;
2347 background-color: #62cffc;
2348 font-size: 10px;
2348 font-size: 10px;
2349 color: #ffffff;
2349 color: #ffffff;
2350 white-space: nowrap;
2350 white-space: nowrap;
2351 border-radius: 3px;
2351 border-radius: 3px;
2352 }
2352 }
2353
2353
2354 .tagtag a,
2354 .tagtag a,
2355 .tagtag a:hover,
2355 .tagtag a:hover,
2356 .logtags .tagtag a,
2356 .logtags .tagtag a,
2357 .logtags .tagtag a:hover {
2357 .logtags .tagtag a:hover {
2358 text-decoration: none;
2358 text-decoration: none;
2359 color: inherit;
2359 color: inherit;
2360 }
2360 }
2361 .logbooks .booktag,
2361 .logbooks .booktag,
2362 .logbooks .booktag,
2362 .logbooks .booktag,
2363 .logtags .booktag,
2363 .logtags .booktag,
2364 .logtags .booktag {
2364 .logtags .booktag {
2365 padding: 1px 3px 1px 3px;
2365 padding: 1px 3px 1px 3px;
2366 background-color: #46A546;
2366 background-color: #46A546;
2367 font-size: 10px;
2367 font-size: 10px;
2368 color: #ffffff;
2368 color: #ffffff;
2369 white-space: nowrap;
2369 white-space: nowrap;
2370 border-radius: 3px;
2370 border-radius: 3px;
2371 }
2371 }
2372 .logbooks .booktag,
2372 .logbooks .booktag,
2373 .logbooks .booktag a,
2373 .logbooks .booktag a,
2374 .right .logtags .booktag,
2374 .right .logtags .booktag,
2375 .logtags .booktag a {
2375 .logtags .booktag a {
2376 color: #ffffff;
2376 color: #ffffff;
2377 }
2377 }
2378
2378
2379 .logbooks .booktag,
2379 .logbooks .booktag,
2380 .logbooks .booktag a:hover,
2380 .logbooks .booktag a:hover,
2381 .logtags .booktag,
2381 .logtags .booktag,
2382 .logtags .booktag a:hover,
2382 .logtags .booktag a:hover,
2383 .booktag a,
2383 .booktag a,
2384 .booktag a:hover {
2384 .booktag a:hover {
2385 text-decoration: none;
2385 text-decoration: none;
2386 color: inherit;
2386 color: inherit;
2387 }
2387 }
2388 div.browserblock {
2388 div.browserblock {
2389 overflow: hidden;
2389 overflow: hidden;
2390 border: 1px solid #ccc;
2390 border: 1px solid #ccc;
2391 background: #f8f8f8;
2391 background: #f8f8f8;
2392 font-size: 100%;
2392 font-size: 100%;
2393 line-height: 125%;
2393 line-height: 125%;
2394 padding: 0;
2394 padding: 0;
2395 border-radius: 6px 6px 0px 0px;
2395 border-radius: 6px 6px 0px 0px;
2396 }
2396 }
2397
2397
2398 div.browserblock .browser-header {
2398 div.browserblock .browser-header {
2399 background: #FFF;
2399 background: #FFF;
2400 padding: 10px 0px 15px 0px;
2400 padding: 10px 0px 15px 0px;
2401 width: 100%;
2401 width: 100%;
2402 }
2402 }
2403
2403
2404 div.browserblock .browser-nav {
2404 div.browserblock .browser-nav {
2405 float: left
2405 float: left
2406 }
2406 }
2407
2407
2408 div.browserblock .browser-branch {
2408 div.browserblock .browser-branch {
2409 float: left;
2409 float: left;
2410 }
2410 }
2411
2411
2412 div.browserblock .browser-branch label {
2412 div.browserblock .browser-branch label {
2413 color: #4A4A4A;
2413 color: #4A4A4A;
2414 vertical-align: text-top;
2414 vertical-align: text-top;
2415 padding-right: 2px;
2415 padding-right: 2px;
2416 }
2416 }
2417
2417
2418 div.browserblock .browser-header span {
2418 div.browserblock .browser-header span {
2419 margin-left: 5px;
2419 margin-left: 5px;
2420 font-weight: 700;
2420 font-weight: 700;
2421 }
2421 }
2422
2422
2423 div.browserblock .browser-search {
2423 div.browserblock .browser-search {
2424 clear: both;
2424 clear: both;
2425 padding: 8px 8px 0px 5px;
2425 padding: 8px 8px 0px 5px;
2426 height: 20px;
2426 height: 20px;
2427 }
2427 }
2428
2428
2429 div.browserblock #node_filter_box {
2429 div.browserblock #node_filter_box {
2430 }
2430 }
2431
2431
2432 div.browserblock .search_activate {
2432 div.browserblock .search_activate {
2433 float: left
2433 float: left
2434 }
2434 }
2435
2435
2436 div.browserblock .add_node {
2436 div.browserblock .add_node {
2437 float: left;
2437 float: left;
2438 padding-left: 5px;
2438 padding-left: 5px;
2439 }
2439 }
2440
2440
2441 div.browserblock .search_activate a:hover,
2441 div.browserblock .search_activate a:hover,
2442 div.browserblock .add_node a:hover {
2442 div.browserblock .add_node a:hover {
2443 text-decoration: none !important;
2443 text-decoration: none !important;
2444 }
2444 }
2445
2445
2446 div.browserblock .browser-body {
2446 div.browserblock .browser-body {
2447 background: #EEE;
2447 background: #EEE;
2448 border-top: 1px solid #CCC;
2448 border-top: 1px solid #CCC;
2449 }
2449 }
2450
2450
2451 table.code-browser {
2451 table.code-browser {
2452 border-collapse: collapse;
2452 border-collapse: collapse;
2453 width: 100%;
2453 width: 100%;
2454 }
2454 }
2455
2455
2456 table.code-browser tr {
2456 table.code-browser tr {
2457 margin: 3px;
2457 margin: 3px;
2458 }
2458 }
2459
2459
2460 table.code-browser thead th {
2460 table.code-browser thead th {
2461 background-color: #EEE;
2461 background-color: #EEE;
2462 height: 20px;
2462 height: 20px;
2463 font-size: 1.1em;
2463 font-size: 1.1em;
2464 font-weight: 700;
2464 font-weight: 700;
2465 text-align: left;
2465 text-align: left;
2466 padding-left: 10px;
2466 padding-left: 10px;
2467 }
2467 }
2468
2468
2469 table.code-browser tbody td {
2469 table.code-browser tbody td {
2470 padding-left: 10px;
2470 padding-left: 10px;
2471 height: 20px;
2471 height: 20px;
2472 }
2472 }
2473
2473
2474 table.code-browser .browser-file {
2474 table.code-browser .browser-file {
2475 height: 16px;
2475 height: 16px;
2476 padding-left: 5px;
2476 padding-left: 5px;
2477 text-align: left;
2477 text-align: left;
2478 }
2478 }
2479 .diffblock .changeset_header {
2479 .diffblock .changeset_header {
2480 height: 16px;
2480 height: 16px;
2481 }
2481 }
2482 .diffblock .changeset_file {
2482 .diffblock .changeset_file {
2483 float: left;
2483 float: left;
2484 }
2484 }
2485 .diffblock .diff-menu-wrapper {
2485 .diffblock .diff-menu-wrapper {
2486 float: left;
2486 float: left;
2487 }
2487 }
2488
2488
2489 .diffblock .diff-menu {
2489 .diffblock .diff-menu {
2490 position: absolute;
2490 position: absolute;
2491 background: none repeat scroll 0 0 #FFFFFF;
2491 background: none repeat scroll 0 0 #FFFFFF;
2492 border-color: #577632 #666666 #666666;
2492 border-color: #577632 #666666 #666666;
2493 border-right: 1px solid #666666;
2493 border-right: 1px solid #666666;
2494 border-style: solid solid solid;
2494 border-style: solid solid solid;
2495 border-width: 1px;
2495 border-width: 1px;
2496 box-shadow: 2px 8px 4px rgba(0, 0, 0, 0.2);
2496 box-shadow: 2px 8px 4px rgba(0, 0, 0, 0.2);
2497 margin-top: 5px;
2497 margin-top: 5px;
2498 margin-left: 1px;
2498 margin-left: 1px;
2499
2499
2500 }
2500 }
2501 .diffblock .diff-actions {
2501 .diffblock .diff-actions {
2502 float: left;
2502 float: left;
2503 }
2503 }
2504 .diffblock .diff-actions span.no-file,
2504 .diffblock .diff-actions span.no-file,
2505 .diffblock .diff-actions span.arrow {
2505 .diffblock .diff-actions span.arrow {
2506 opacity: 0.5;
2506 opacity: 0.5;
2507 }
2507 }
2508 .diffblock .diff-actions span.arrow {
2508 .diffblock .diff-actions span.arrow {
2509 margin: 0 -3px;
2509 margin: 0 -3px;
2510 }
2510 }
2511 .diffblock .diff-actions a i {
2511 .diffblock .diff-actions a i {
2512 margin: 0 2px;
2512 margin: 0 2px;
2513 }
2513 }
2514 .diffblock.twoway {
2514 .diffblock.twoway {
2515 overflow: visible;
2515 overflow: visible;
2516 }
2516 }
2517 .diffblock.twoway .diff-actions {
2517 .diffblock.twoway .diff-actions {
2518 padding-top: 0;
2518 padding-top: 0;
2519 }
2519 }
2520 .diffblock.twoway .diff-actions label input {
2520 .diffblock.twoway .diff-actions label input {
2521 margin: -5px 5px 0 10px;
2521 margin: -5px 5px 0 10px;
2522 position: relative;
2522 position: relative;
2523 top: 3px;
2523 top: 3px;
2524 }
2524 }
2525 .diffblock .diff-menu ul li {
2525 .diffblock .diff-menu ul li {
2526 padding: 0px 0px 0px 0px !important;
2526 padding: 0px 0px 0px 0px !important;
2527 }
2527 }
2528 .diffblock .diff-menu ul li a {
2528 .diffblock .diff-menu ul li a {
2529 display: block;
2529 display: block;
2530 padding: 3px 8px 3px 8px !important;
2530 padding: 3px 8px 3px 8px !important;
2531 }
2531 }
2532 .diffblock .diff-menu ul li a:hover {
2532 .diffblock .diff-menu ul li a:hover {
2533 text-decoration: none;
2533 text-decoration: none;
2534 background-color: #EEEEEE;
2534 background-color: #EEEEEE;
2535 }
2535 }
2536 table.code-browser .browser-dir {
2536 table.code-browser .browser-dir {
2537 height: 16px;
2537 height: 16px;
2538 padding-left: 5px;
2538 padding-left: 5px;
2539 text-align: left;
2539 text-align: left;
2540 }
2540 }
2541
2541
2542 table.code-browser .submodule-dir {
2542 table.code-browser .submodule-dir {
2543 height: 16px;
2543 height: 16px;
2544 padding-left: 5px;
2544 padding-left: 5px;
2545 text-align: left;
2545 text-align: left;
2546 }
2546 }
2547
2547
2548 /* add some padding to the right of the file, folder, or submodule icon and
2548 /* add some padding to the right of the file, folder, or submodule icon and
2549 before the text */
2549 before the text */
2550 table.code-browser i[class^='icon-'] {
2550 table.code-browser i[class^='icon-'] {
2551 padding-right: .3em;
2551 padding-right: .3em;
2552 }
2552 }
2553
2553
2554 .panel .search {
2554 .panel .search {
2555 clear: both;
2555 clear: both;
2556 overflow: hidden;
2556 overflow: hidden;
2557 margin: 0;
2557 margin: 0;
2558 padding: 0 20px 10px;
2558 padding: 0 20px 10px;
2559 }
2559 }
2560
2560
2561 .panel .search div.search_path {
2561 .panel .search div.search_path {
2562 background: none repeat scroll 0 0 #EEE;
2562 background: none repeat scroll 0 0 #EEE;
2563 border: 1px solid #CCC;
2563 border: 1px solid #CCC;
2564 color: blue;
2564 color: blue;
2565 margin-bottom: 10px;
2565 margin-bottom: 10px;
2566 padding: 10px 0;
2566 padding: 10px 0;
2567 }
2567 }
2568
2568
2569 .panel .search div.search_path div.link {
2569 .panel .search div.search_path div.link {
2570 font-weight: 700;
2570 font-weight: 700;
2571 margin-left: 25px;
2571 margin-left: 25px;
2572 }
2572 }
2573
2573
2574 .panel .search div.search_path div.link a {
2574 .panel .search div.search_path div.link a {
2575 color: #577632;
2575 color: #577632;
2576 cursor: pointer;
2576 cursor: pointer;
2577 text-decoration: none;
2577 text-decoration: none;
2578 }
2578 }
2579
2579
2580 #path_unlock {
2580 #path_unlock {
2581 color: red;
2581 color: red;
2582 font-size: 1.2em;
2582 font-size: 1.2em;
2583 padding-left: 4px;
2583 padding-left: 4px;
2584 }
2584 }
2585
2585
2586 .info_box span {
2586 .info_box span {
2587 margin-left: 3px;
2587 margin-left: 3px;
2588 margin-right: 3px;
2588 margin-right: 3px;
2589 }
2589 }
2590
2590
2591 .info_box .rev {
2591 .info_box .rev {
2592 color: #577632;
2592 color: #577632;
2593 font-size: 1.6em;
2593 font-size: 1.6em;
2594 font-weight: bold;
2594 font-weight: bold;
2595 vertical-align: sub;
2595 vertical-align: sub;
2596 }
2596 }
2597
2597
2598 .info_box input#at_rev,
2598 .info_box input#at_rev,
2599 .info_box input#size {
2599 .info_box input#size {
2600 background: #FFF;
2600 background: #FFF;
2601 border-top: 1px solid #b3b3b3;
2601 border-top: 1px solid #b3b3b3;
2602 border-left: 1px solid #b3b3b3;
2602 border-left: 1px solid #b3b3b3;
2603 border-right: 1px solid #eaeaea;
2603 border-right: 1px solid #eaeaea;
2604 border-bottom: 1px solid #eaeaea;
2604 border-bottom: 1px solid #eaeaea;
2605 color: #000;
2605 color: #000;
2606 font-size: 12px;
2606 font-size: 12px;
2607 margin: 0;
2607 margin: 0;
2608 padding: 1px 5px 1px;
2608 padding: 1px 5px 1px;
2609 }
2609 }
2610
2610
2611 .info_box input#view {
2611 .info_box input#view {
2612 text-align: center;
2612 text-align: center;
2613 padding: 4px 3px 2px 2px;
2613 padding: 4px 3px 2px 2px;
2614 }
2614 }
2615
2615
2616 .info_box_elem {
2616 .info_box_elem {
2617 display: inline-block;
2617 display: inline-block;
2618 padding: 0 2px;
2618 padding: 0 2px;
2619 }
2619 }
2620
2620
2621 .yui-overlay, .yui-panel-container {
2621 .yui-overlay, .yui-panel-container {
2622 visibility: hidden;
2622 visibility: hidden;
2623 position: absolute;
2623 position: absolute;
2624 z-index: 2;
2624 z-index: 2;
2625 }
2625 }
2626
2626
2627 #tip-box {
2628 position: absolute;
2629
2630 background-color: #FFF;
2631 border: 2px solid #577632;
2632 font: 100% sans-serif;
2633 width: auto;
2634 opacity: 1;
2635 padding: 8px;
2636
2637 white-space: pre-wrap;
2638 border-radius: 8px 8px 8px 8px;
2639 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
2640 z-index: 100000;
2641 }
2642
2643 .hl-tip-box {
2644 z-index: 1;
2645 position: absolute;
2646 color: #666;
2647 background-color: #FFF;
2648 border: 2px solid #577632;
2649 font: 100% sans-serif;
2650 width: auto;
2651 opacity: 1;
2652 padding: 8px;
2653 white-space: pre-wrap;
2654 border-radius: 8px 8px 8px 8px;
2655 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
2656 }
2657
2658
2627
2659 .mentions-container {
2628 .mentions-container {
2660 width: 90% !important;
2629 width: 90% !important;
2661 }
2630 }
2662 .mentions-container .yui-ac-content {
2631 .mentions-container .yui-ac-content {
2663 width: 100% !important;
2632 width: 100% !important;
2664 }
2633 }
2665
2634
2666 .ac {
2635 .ac {
2667 vertical-align: top;
2636 vertical-align: top;
2668 }
2637 }
2669
2638
2670 .ac .yui-ac {
2639 .ac .yui-ac {
2671 position: inherit;
2640 position: inherit;
2672 font-size: 100%;
2641 font-size: 100%;
2673 }
2642 }
2674
2643
2675 .ac .perm_ac {
2644 .ac .perm_ac {
2676 width: 20em;
2645 width: 20em;
2677 }
2646 }
2678
2647
2679 .ac .yui-ac-input {
2648 .ac .yui-ac-input {
2680 width: 100%;
2649 width: 100%;
2681 }
2650 }
2682
2651
2683 .ac .yui-ac-container {
2652 .ac .yui-ac-container {
2684 position: absolute;
2653 position: absolute;
2685 top: 1.6em;
2654 top: 1.6em;
2686 width: auto;
2655 width: auto;
2687 }
2656 }
2688
2657
2689 .ac .yui-ac-content {
2658 .ac .yui-ac-content {
2690 position: absolute;
2659 position: absolute;
2691 border: 1px solid gray;
2660 border: 1px solid gray;
2692 background: #fff;
2661 background: #fff;
2693 z-index: 9050;
2662 z-index: 9050;
2694 }
2663 }
2695
2664
2696 .ac .yui-ac-shadow {
2665 .ac .yui-ac-shadow {
2697 position: absolute;
2666 position: absolute;
2698 width: 100%;
2667 width: 100%;
2699 background: #000;
2668 background: #000;
2700 opacity: .10;
2669 opacity: .10;
2701 z-index: 9049;
2670 z-index: 9049;
2702 margin: .3em;
2671 margin: .3em;
2703 }
2672 }
2704
2673
2705 .ac .yui-ac-content ul {
2674 .ac .yui-ac-content ul {
2706 width: 100%;
2675 width: 100%;
2707 margin: 0;
2676 margin: 0;
2708 padding: 0;
2677 padding: 0;
2709 z-index: 9050;
2678 z-index: 9050;
2710 }
2679 }
2711
2680
2712 .ac .yui-ac-content li {
2681 .ac .yui-ac-content li {
2713 cursor: default;
2682 cursor: default;
2714 white-space: nowrap;
2683 white-space: nowrap;
2715 margin: 0;
2684 margin: 0;
2716 padding: 2px 5px;
2685 padding: 2px 5px;
2717 height: 18px;
2686 height: 18px;
2718 z-index: 9050;
2687 z-index: 9050;
2719 display: block;
2688 display: block;
2720 width: auto !important;
2689 width: auto !important;
2721 }
2690 }
2722
2691
2723 .ac .yui-ac-content li .ac-container-wrap {
2692 .ac .yui-ac-content li .ac-container-wrap {
2724 width: auto;
2693 width: auto;
2725 }
2694 }
2726
2695
2727 .ac .yui-ac-content li.yui-ac-prehighlight {
2696 .ac .yui-ac-content li.yui-ac-prehighlight {
2728 background: #B3D4FF;
2697 background: #B3D4FF;
2729 z-index: 9050;
2698 z-index: 9050;
2730 }
2699 }
2731
2700
2732 .ac .yui-ac-content li.yui-ac-highlight {
2701 .ac .yui-ac-content li.yui-ac-highlight {
2733 background: #556CB5;
2702 background: #556CB5;
2734 color: #FFF;
2703 color: #FFF;
2735 z-index: 9050;
2704 z-index: 9050;
2736 }
2705 }
2737 .ac .yui-ac-bd {
2706 .ac .yui-ac-bd {
2738 z-index: 9050;
2707 z-index: 9050;
2739 }
2708 }
2740
2709
2741 #repo_size {
2710 #repo_size {
2742 display: block;
2711 display: block;
2743 margin-top: 4px;
2712 margin-top: 4px;
2744 color: #666;
2713 color: #666;
2745 float: right;
2714 float: right;
2746 }
2715 }
2747
2716
2748 .currently_following {
2717 .currently_following {
2749 padding-left: 10px;
2718 padding-left: 10px;
2750 padding-bottom: 5px;
2719 padding-bottom: 5px;
2751 }
2720 }
2752
2721
2753 #switch_repos {
2722 #switch_repos {
2754 position: absolute;
2723 position: absolute;
2755 height: 25px;
2724 height: 25px;
2756 z-index: 1;
2725 z-index: 1;
2757 }
2726 }
2758
2727
2759 #switch_repos select {
2728 #switch_repos select {
2760 min-width: 150px;
2729 min-width: 150px;
2761 max-height: 250px;
2730 max-height: 250px;
2762 z-index: 1;
2731 z-index: 1;
2763 }
2732 }
2764
2733
2765 .breadcrumbs {
2734 .breadcrumbs {
2766 border: medium none;
2735 border: medium none;
2767 color: #FFF;
2736 color: #FFF;
2768 font-weight: 700;
2737 font-weight: 700;
2769 font-size: 14px;
2738 font-size: 14px;
2770 }
2739 }
2771
2740
2772 .breadcrumbs .hash {
2741 .breadcrumbs .hash {
2773 text-transform: none;
2742 text-transform: none;
2774 color: #fff;
2743 color: #fff;
2775 }
2744 }
2776
2745
2777 .flash_msg {
2746 .flash_msg {
2778 }
2747 }
2779
2748
2780 .flash_msg ul {
2749 .flash_msg ul {
2781 }
2750 }
2782
2751
2783 .error_red {
2752 .error_red {
2784 color: red;
2753 color: red;
2785 }
2754 }
2786
2755
2787 .flash_msg .alert-error {
2756 .flash_msg .alert-error {
2788 background-color: #c43c35;
2757 background-color: #c43c35;
2789 background-repeat: repeat-x;
2758 background-repeat: repeat-x;
2790 background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);
2759 background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);
2791 border-color: #c43c35 #c43c35 #882a25;
2760 border-color: #c43c35 #c43c35 #882a25;
2792 }
2761 }
2793
2762
2794 .flash_msg .alert-error a {
2763 .flash_msg .alert-error a {
2795 text-decoration: underline;
2764 text-decoration: underline;
2796 }
2765 }
2797
2766
2798 .flash_msg .alert-warning {
2767 .flash_msg .alert-warning {
2799 color: #404040 !important;
2768 color: #404040 !important;
2800 background-color: #eedc94;
2769 background-color: #eedc94;
2801 background-repeat: repeat-x;
2770 background-repeat: repeat-x;
2802 background-image: linear-gradient(to bottom, #fceec1, #eedc94);
2771 background-image: linear-gradient(to bottom, #fceec1, #eedc94);
2803 border-color: #eedc94 #eedc94 #e4c652;
2772 border-color: #eedc94 #eedc94 #e4c652;
2804 }
2773 }
2805
2774
2806 .flash_msg .alert-warning a {
2775 .flash_msg .alert-warning a {
2807 text-decoration: underline;
2776 text-decoration: underline;
2808 }
2777 }
2809
2778
2810 .flash_msg .alert-success {
2779 .flash_msg .alert-success {
2811 background-color: #57a957;
2780 background-color: #57a957;
2812 background-repeat: repeat-x !important;
2781 background-repeat: repeat-x !important;
2813 background-image: linear-gradient(to bottom, #62c462, #57a957);
2782 background-image: linear-gradient(to bottom, #62c462, #57a957);
2814 border-color: #57a957 #57a957 #3d773d;
2783 border-color: #57a957 #57a957 #3d773d;
2815 }
2784 }
2816
2785
2817 .flash_msg .alert-success a {
2786 .flash_msg .alert-success a {
2818 text-decoration: underline;
2787 text-decoration: underline;
2819 color: #FFF !important;
2788 color: #FFF !important;
2820 }
2789 }
2821
2790
2822 .flash_msg .alert-info {
2791 .flash_msg .alert-info {
2823 background-color: #339bb9;
2792 background-color: #339bb9;
2824 background-repeat: repeat-x;
2793 background-repeat: repeat-x;
2825 background-image: linear-gradient(to bottom, #5bc0de, #339bb9);
2794 background-image: linear-gradient(to bottom, #5bc0de, #339bb9);
2826 border-color: #339bb9 #339bb9 #22697d;
2795 border-color: #339bb9 #339bb9 #22697d;
2827 }
2796 }
2828
2797
2829 .flash_msg .alert-info a {
2798 .flash_msg .alert-info a {
2830 text-decoration: underline;
2799 text-decoration: underline;
2831 }
2800 }
2832
2801
2833 .flash_msg .alert-error,
2802 .flash_msg .alert-error,
2834 .flash_msg .alert-warning,
2803 .flash_msg .alert-warning,
2835 .flash_msg .alert-success,
2804 .flash_msg .alert-success,
2836 .flash_msg .alert-info {
2805 .flash_msg .alert-info {
2837 font-size: 12px;
2806 font-size: 12px;
2838 font-weight: 700;
2807 font-weight: 700;
2839 min-height: 14px;
2808 min-height: 14px;
2840 line-height: 14px;
2809 line-height: 14px;
2841 margin-bottom: 10px;
2810 margin-bottom: 10px;
2842 margin-top: 0;
2811 margin-top: 0;
2843 display: block;
2812 display: block;
2844 overflow: auto;
2813 overflow: auto;
2845 padding: 6px 10px 6px 10px;
2814 padding: 6px 10px 6px 10px;
2846 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
2815 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
2847 position: relative;
2816 position: relative;
2848 color: #FFF;
2817 color: #FFF;
2849 border-width: 1px;
2818 border-width: 1px;
2850 border-style: solid;
2819 border-style: solid;
2851 border-radius: 4px;
2820 border-radius: 4px;
2852 box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
2821 box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
2853 }
2822 }
2854
2823
2855 div#legend_data {
2824 div#legend_data {
2856 padding-left: 10px;
2825 padding-left: 10px;
2857 }
2826 }
2858 div#legend_container table {
2827 div#legend_container table {
2859 border: none !important;
2828 border: none !important;
2860 }
2829 }
2861 div#legend_container table,
2830 div#legend_container table,
2862 div#legend_choices table {
2831 div#legend_choices table {
2863 width: auto !important;
2832 width: auto !important;
2864 }
2833 }
2865
2834
2866 table#permissions_manage span.private_repo_msg {
2835 table#permissions_manage span.private_repo_msg {
2867 font-size: 0.8em;
2836 font-size: 0.8em;
2868 opacity: 0.6;
2837 opacity: 0.6;
2869 }
2838 }
2870
2839
2871 table#permissions_manage td.private_repo_msg {
2840 table#permissions_manage td.private_repo_msg {
2872 font-size: 0.8em;
2841 font-size: 0.8em;
2873 }
2842 }
2874
2843
2875 table#permissions_manage tr#add_perm_input td {
2844 table#permissions_manage tr#add_perm_input td {
2876 vertical-align: middle;
2845 vertical-align: middle;
2877 }
2846 }
2878
2847
2879 div.gravatar {
2848 div.gravatar {
2880 float: left;
2849 float: left;
2881 background-color: #FFF;
2850 background-color: #FFF;
2882 margin-right: 0.7em;
2851 margin-right: 0.7em;
2883 padding: 1px 1px 1px 1px;
2852 padding: 1px 1px 1px 1px;
2884 line-height: 0;
2853 line-height: 0;
2885 border-radius: 3px;
2854 border-radius: 3px;
2886 }
2855 }
2887
2856
2888 div.gravatar img {
2857 div.gravatar img {
2889 border-radius: 2px;
2858 border-radius: 2px;
2890 }
2859 }
2891
2860
2892 nav.navbar, #content, #footer {
2861 nav.navbar, #content, #footer {
2893 min-width: 978px;
2862 min-width: 978px;
2894 }
2863 }
2895
2864
2896 #content {
2865 #content {
2897 clear: both;
2866 clear: both;
2898 padding: 10px 10px 14px 10px;
2867 padding: 10px 10px 14px 10px;
2899 }
2868 }
2900
2869
2901 #content.hover {
2870 #content.hover {
2902 padding: 55px 10px 14px 10px !important;
2871 padding: 55px 10px 14px 10px !important;
2903 }
2872 }
2904
2873
2905 #content div.panel div.panel-heading div.search {
2874 #content div.panel div.panel-heading div.search {
2906 border-left: 1px solid #576622;
2875 border-left: 1px solid #576622;
2907 }
2876 }
2908
2877
2909 #content div.panel div.panel-heading div.search > div input {
2878 #content div.panel div.panel-heading div.search > div input {
2910 border: 1px solid #576622;
2879 border: 1px solid #576622;
2911 }
2880 }
2912
2881
2913 .label,
2882 .label,
2914 .btn {
2883 .btn {
2915 color: #515151 !important;
2884 color: #515151 !important;
2916 background-color: #DADADA;
2885 background-color: #DADADA;
2917 background-repeat: repeat-x;
2886 background-repeat: repeat-x;
2918 background-image: linear-gradient(to bottom, #F4F4F4, #DADADA);
2887 background-image: linear-gradient(to bottom, #F4F4F4, #DADADA);
2919
2888
2920 border-top: 1px solid #DDD;
2889 border-top: 1px solid #DDD;
2921 border-left: 1px solid #c6c6c6;
2890 border-left: 1px solid #c6c6c6;
2922 border-right: 1px solid #DDD;
2891 border-right: 1px solid #DDD;
2923 border-bottom: 1px solid #c6c6c6;
2892 border-bottom: 1px solid #c6c6c6;
2924 outline: none;
2893 outline: none;
2925 margin: 0 3px 0 0;
2894 margin: 0 3px 0 0;
2926 border-radius: 4px 4px 4px 4px !important;
2895 border-radius: 4px 4px 4px 4px !important;
2927 padding: 3px 3px 3px 3px;
2896 padding: 3px 3px 3px 3px;
2928 display: inline-block;
2897 display: inline-block;
2929 white-space: nowrap;
2898 white-space: nowrap;
2930 }
2899 }
2931 .btn {
2900 .btn {
2932 cursor: pointer !important;
2901 cursor: pointer !important;
2933 }
2902 }
2934 .label {
2903 .label {
2935 cursor: default !important;
2904 cursor: default !important;
2936 }
2905 }
2937
2906
2938 .panel-body.settings > ul.nav-stacked {
2907 .panel-body.settings > ul.nav-stacked {
2939 float: left;
2908 float: left;
2940 width: 150px;
2909 width: 150px;
2941 margin: 20px;
2910 margin: 20px;
2942 color: #393939;
2911 color: #393939;
2943 font-weight: 700;
2912 font-weight: 700;
2944 }
2913 }
2945
2914
2946 .panel-body.settings > ul.nav-stacked a {
2915 .panel-body.settings > ul.nav-stacked a {
2947 color: inherit;
2916 color: inherit;
2948 }
2917 }
2949
2918
2950 .panel-body.settings > ul.nav-stacked li.active {
2919 .panel-body.settings > ul.nav-stacked li.active {
2951 list-style-type: disc
2920 list-style-type: disc
2952 }
2921 }
2953
2922
2954 .panel-body.settings > div,
2923 .panel-body.settings > div,
2955 .panel-body.settings > form {
2924 .panel-body.settings > form {
2956 float: left;
2925 float: left;
2957 width: 750px;
2926 width: 750px;
2958 margin: 10px 0 0 0;
2927 margin: 10px 0 0 0;
2959 border-left: 1px solid #DDDDDD;
2928 border-left: 1px solid #DDDDDD;
2960 }
2929 }
2961
2930
2962 .panel-body > div,
2931 .panel-body > div,
2963 .panel-body > form {
2932 .panel-body > form {
2964 padding: 0 20px 10px;
2933 padding: 0 20px 10px;
2965 }
2934 }
2966
2935
2967 /* make .btn inputs and buttons and divs look the same */
2936 /* make .btn inputs and buttons and divs look the same */
2968 button.btn,
2937 button.btn,
2969 input.btn {
2938 input.btn {
2970 font-family: inherit;
2939 font-family: inherit;
2971 font-size: inherit;
2940 font-size: inherit;
2972 line-height: inherit;
2941 line-height: inherit;
2973 }
2942 }
2974
2943
2975 .btn::-moz-focus-inner {
2944 .btn::-moz-focus-inner {
2976 border: 0;
2945 border: 0;
2977 padding: 0;
2946 padding: 0;
2978 }
2947 }
2979
2948
2980 .btn.badge {
2949 .btn.badge {
2981 cursor: default !important;
2950 cursor: default !important;
2982 }
2951 }
2983
2952
2984 input[disabled].btn,
2953 input[disabled].btn,
2985 .btn.disabled {
2954 .btn.disabled {
2986 color: #999;
2955 opacity: 0.5;
2987 }
2956 }
2988
2957
2989 .label,
2958 .label,
2990 .btn.btn-sm {
2959 .btn.btn-sm {
2991 padding: 3px 8px;
2960 padding: 3px 8px;
2992 }
2961 }
2993
2962
2994 .btn.btn-xs {
2963 .btn.btn-xs {
2995 padding: 1px 5px;
2964 padding: 1px 5px;
2996 }
2965 }
2997
2966
2998 .btn:focus {
2967 .btn:focus {
2999 outline: none;
2968 outline: none;
3000 }
2969 }
3001 .btn:hover {
2970 .btn:hover {
3002 text-decoration: none;
2971 text-decoration: none;
3003 color: #515151;
2972 color: #515151;
3004 box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25), 0 0 3px #FFFFFF !important;
2973 box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25), 0 0 3px #FFFFFF !important;
3005 }
2974 }
3006 .btn.badge:hover {
2975 .btn.badge:hover {
3007 box-shadow: none !important;
2976 box-shadow: none !important;
3008 }
2977 }
3009 .btn.disabled:hover {
2978 .btn.disabled:hover {
3010 background-position: 0;
2979 background-position: 0;
3011 color: #999;
2980 color: #999;
3012 text-decoration: none;
2981 text-decoration: none;
3013 box-shadow: none !important;
2982 box-shadow: none !important;
3014 }
2983 }
3015
2984
3016 .label.label-danger,
2985 .label.label-danger,
3017 .btn.btn-danger {
2986 .btn.btn-danger {
3018 color: #fff !important;
2987 color: #fff !important;
3019 background-color: #c43c35;
2988 background-color: #c43c35;
3020 background-repeat: repeat-x;
2989 background-repeat: repeat-x;
3021 background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);
2990 background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);
3022 border-color: #c43c35 #c43c35 #882a25;
2991 border-color: #c43c35 #c43c35 #882a25;
3023 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
2992 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3024 }
2993 }
3025
2994
3026 .label.label-primary,
2995 .label.label-primary,
3027 .btn.btn-primary {
2996 .btn.btn-primary {
3028 color: #fff !important;
2997 color: #fff !important;
3029 background-color: #339bb9;
2998 background-color: #339bb9;
3030 background-repeat: repeat-x;
2999 background-repeat: repeat-x;
3031 background-image: linear-gradient(to bottom, #5bc0de, #339bb9);
3000 background-image: linear-gradient(to bottom, #5bc0de, #339bb9);
3032 border-color: #339bb9 #339bb9 #22697d;
3001 border-color: #339bb9 #339bb9 #22697d;
3033 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3002 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3034 }
3003 }
3035
3004
3036 .label.label-success,
3005 .label.label-success,
3037 .btn.btn-success {
3006 .btn.btn-success {
3038 color: #fff !important;
3007 color: #fff !important;
3039 background-color: #57a957;
3008 background-color: #57a957;
3040 background-repeat: repeat-x;
3009 background-repeat: repeat-x;
3041 background-image: linear-gradient(to bottom, #62c462, #57a957);
3010 background-image: linear-gradient(to bottom, #62c462, #57a957);
3042 border-color: #57a957 #57a957 #3d773d;
3011 border-color: #57a957 #57a957 #3d773d;
3043 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3012 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3044 }
3013 }
3045
3014
3046 .label.label-warning,
3015 .label.label-warning,
3047 .btn.btn-warning {
3016 .btn.btn-warning {
3048 color: #fff !important;
3017 color: #fff !important;
3049 background-color: #faa732;
3018 background-color: #faa732;
3050 background-repeat: repeat-x;
3019 background-repeat: repeat-x;
3051 background-image: linear-gradient(to bottom, #fbb450, #f89406);
3020 background-image: linear-gradient(to bottom, #fbb450, #f89406);
3052 border-color: #f89406 #f89406 #ad6704;
3021 border-color: #f89406 #f89406 #ad6704;
3053 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3022 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3054 }
3023 }
3055
3024
3056 label.disabled {
3025 label.disabled {
3057 color: #aaa !important;
3026 color: #aaa !important;
3058 }
3027 }
3059
3028
3060 .btn.active {
3029 .btn.active {
3061 font-weight: bold;
3030 font-weight: bold;
3062 }
3031 }
3063
3032
3064 .alert {
3033 .alert {
3065 padding: 15px;
3034 padding: 15px;
3066 margin: 20px 0;
3035 margin: 20px 0;
3067 border: 1px solid transparent;
3036 border: 1px solid transparent;
3068 border-radius: 4px;
3037 border-radius: 4px;
3069 }
3038 }
3070
3039
3071 .alert-success {
3040 .alert-success {
3072 color: #3c763d;
3041 color: #3c763d;
3073 background-color: #dff0d8;
3042 background-color: #dff0d8;
3074 border-color: #d6e9c6;
3043 border-color: #d6e9c6;
3075 }
3044 }
3076
3045
3077 .alert-info {
3046 .alert-info {
3078 color: #31708f;
3047 color: #31708f;
3079 background-color: #d9edf7;
3048 background-color: #d9edf7;
3080 border-color: #bce8f1;
3049 border-color: #bce8f1;
3081 }
3050 }
3082
3051
3083 .alert-warning {
3052 .alert-warning {
3084 color: #8a6d3b;
3053 color: #8a6d3b;
3085 background-color: #fcf8e3;
3054 background-color: #fcf8e3;
3086 border-color: #faebcc;
3055 border-color: #faebcc;
3087 }
3056 }
3088
3057
3089 .alert-danger {
3058 .alert-danger {
3090 color: #a94442;
3059 color: #a94442;
3091 background-color: #f2dede;
3060 background-color: #f2dede;
3092 border-color: #ebccd1;
3061 border-color: #ebccd1;
3093 }
3062 }
3094
3063
3095 ins, div.options a:hover {
3064 ins, div.options a:hover {
3096 text-decoration: none;
3065 text-decoration: none;
3097 }
3066 }
3098
3067
3099 img,
3068 img,
3100 nav.navbar #quick li a:hover span.normal,
3069 nav.navbar #quick li a:hover span.normal,
3101 #clone_url,
3070 #clone_url,
3102 #clone_url_id
3071 #clone_url_id
3103 {
3072 {
3104 border: none;
3073 border: none;
3105 }
3074 }
3106
3075
3107 img.icon, .right .merge img {
3076 img.icon, .right .merge img {
3108 vertical-align: bottom;
3077 vertical-align: bottom;
3109 }
3078 }
3110
3079
3111 nav.navbar ul#logged-user,
3080 nav.navbar ul#logged-user,
3112 #content div.panel div.panel-heading ul.links,
3081 #content div.panel div.panel-heading ul.links,
3113 #content div.panel div.message div.dismiss,
3082 #content div.panel div.message div.dismiss,
3114 #content div.panel div.traffic div.legend ul {
3083 #content div.panel div.traffic div.legend ul {
3115 float: right;
3084 float: right;
3116 margin: 0;
3085 margin: 0;
3117 padding: 0;
3086 padding: 0;
3118 }
3087 }
3119
3088
3120 nav.navbar #home,
3089 nav.navbar #home,
3121 nav.navbar #logo,
3090 nav.navbar #logo,
3122 #content div.panel ul.left,
3091 #content div.panel ul.left,
3123 #content div.panel ol.left,
3092 #content div.panel ol.left,
3124 div#commit_history,
3093 div#commit_history,
3125 div#legend_data, div#legend_container, div#legend_choices {
3094 div#legend_data, div#legend_container, div#legend_choices {
3126 float: left;
3095 float: left;
3127 }
3096 }
3128
3097
3129 nav.navbar #quick li .dropdown-menu,
3098 nav.navbar #quick li .dropdown-menu,
3130 #content #left #menu ul.closed,
3099 #content #left #menu ul.closed,
3131 #content #left #menu li ul.collapsed,
3100 #content #left #menu li ul.collapsed,
3132 .yui-tt-shadow {
3101 .yui-tt-shadow {
3133 display: none;
3102 display: none;
3134 }
3103 }
3135
3104
3136 .dropdown.open .dropdown-menu,
3105 .dropdown.open .dropdown-menu,
3137 #content #left #menu ul.opened,
3106 #content #left #menu ul.opened,
3138 #content #left #menu li ul.expanded {
3107 #content #left #menu li ul.expanded {
3139 display: block !important;
3108 display: block !important;
3140 }
3109 }
3141
3110
3142 .caret:after {
3111 .caret:after {
3143 font-family: 'kallithea';
3112 font-family: 'kallithea';
3144 content: ' \23f7'; /* triangle-down */
3113 content: ' \23f7'; /* triangle-down */
3145 }
3114 }
3146
3115
3147 .branch-switcher .select2-choice,
3116 .branch-switcher .select2-choice,
3148 .repo-switcher .select2-choice {
3117 .repo-switcher .select2-choice {
3149 padding: 0px 8px 1px !important;
3118 padding: 0px 8px 1px !important;
3150 display: block;
3119 display: block;
3151 height: 100%;
3120 height: 100%;
3152 }
3121 }
3153
3122
3154 .branch-switcher .select2-container,
3123 .branch-switcher .select2-container,
3155 .branch-switcher .select2-choice,
3124 .branch-switcher .select2-choice,
3156 .branch-switcher .select2-choice span,
3125 .branch-switcher .select2-choice span,
3157 .repo-switcher .select2-container,
3126 .repo-switcher .select2-container,
3158 .repo-switcher .select2-choice,
3127 .repo-switcher .select2-choice,
3159 .repo-switcher .select2-choice span {
3128 .repo-switcher .select2-choice span {
3160 background: transparent !important;
3129 background: transparent !important;
3161 border: 0 !important;
3130 border: 0 !important;
3162 box-shadow: none !important;
3131 box-shadow: none !important;
3163 color: #FFFFFF !important;
3132 color: #FFFFFF !important;
3164 }
3133 }
3165
3134
3166 .branch-switcher .select2-arrow,
3135 .branch-switcher .select2-arrow,
3167 .repo-switcher .select2-arrow {
3136 .repo-switcher .select2-arrow {
3168 display: none !important;
3137 display: none !important;
3169 }
3138 }
3170
3139
3171 .branch-switcher-dropdown.select2-drop.select2-drop-active,
3140 .branch-switcher-dropdown.select2-drop.select2-drop-active,
3172 .repo-switcher-dropdown.select2-drop.select2-drop-active {
3141 .repo-switcher-dropdown.select2-drop.select2-drop-active {
3173 box-shadow: none;
3142 box-shadow: none;
3174 color: #fff;
3143 color: #fff;
3175 background-color: #576622;
3144 background-color: #576622;
3176 }
3145 }
3177
3146
3178 .branch-switcher-dropdown.select2-drop.select2-drop-active .select2-results .select2-highlighted,
3147 .branch-switcher-dropdown.select2-drop.select2-drop-active .select2-results .select2-highlighted,
3179 .repo-switcher-dropdown.select2-drop.select2-drop-active .select2-results .select2-highlighted {
3148 .repo-switcher-dropdown.select2-drop.select2-drop-active .select2-results .select2-highlighted {
3180 background-color: #6388ad;
3149 background-color: #6388ad;
3181 }
3150 }
3182
3151
3183 #content div.graph {
3152 #content div.graph {
3184 padding: 0 10px 10px;
3153 padding: 0 10px 10px;
3185 height: 450px;
3154 height: 450px;
3186 }
3155 }
3187
3156
3188 #content div.panel ol.lower-roman,
3157 #content div.panel ol.lower-roman,
3189 #content div.panel ol.upper-roman,
3158 #content div.panel ol.upper-roman,
3190 #content div.panel ol.lower-alpha,
3159 #content div.panel ol.lower-alpha,
3191 #content div.panel ol.upper-alpha,
3160 #content div.panel ol.upper-alpha,
3192 #content div.panel ol.decimal {
3161 #content div.panel ol.decimal {
3193 margin: 10px 24px 10px 44px;
3162 margin: 10px 24px 10px 44px;
3194 }
3163 }
3195
3164
3196 #content div.panel div.form div.form-horizontal div.form-group > div input.error,
3165 #content div.panel div.form div.form-horizontal div.form-group > div input.error,
3197 #login div.form div.form-horizontal div.form-group > div input.error,
3166 #login div.form div.form-horizontal div.form-group > div input.error,
3198 #register div.form div.form-horizontal div.form-group > div input.error {
3167 #register div.form div.form-horizontal div.form-group > div input.error {
3199 background: #FBE3E4;
3168 background: #FBE3E4;
3200 border-top: 1px solid #e1b2b3;
3169 border-top: 1px solid #e1b2b3;
3201 border-left: 1px solid #e1b2b3;
3170 border-left: 1px solid #e1b2b3;
3202 border-right: 1px solid #FBC2C4;
3171 border-right: 1px solid #FBC2C4;
3203 border-bottom: 1px solid #FBC2C4;
3172 border-bottom: 1px solid #FBC2C4;
3204 }
3173 }
3205
3174
3206 #content div.panel div.form div.form-horizontal div.form-group > div input.success,
3175 #content div.panel div.form div.form-horizontal div.form-group > div input.success,
3207 #login div.form div.form-horizontal div.form-group > div input.success,
3176 #login div.form div.form-horizontal div.form-group > div input.success,
3208 #register div.form div.form-horizontal div.form-group > div input.success {
3177 #register div.form div.form-horizontal div.form-group > div input.success {
3209 background: #E6EFC2;
3178 background: #E6EFC2;
3210 border-top: 1px solid #cebb98;
3179 border-top: 1px solid #cebb98;
3211 border-left: 1px solid #cebb98;
3180 border-left: 1px solid #cebb98;
3212 border-right: 1px solid #c6d880;
3181 border-right: 1px solid #c6d880;
3213 border-bottom: 1px solid #c6d880;
3182 border-bottom: 1px solid #c6d880;
3214 }
3183 }
3215
3184
3216 #content div.panel div.form div.form-horizontal div.form-group > div select,
3185 #content div.panel div.form div.form-horizontal div.form-group > div select,
3217 #content div.panel table th.selected input,
3186 #content div.panel table th.selected input,
3218 #content div.panel table td.selected input {
3187 #content div.panel table td.selected input {
3219 margin: 0;
3188 margin: 0;
3220 }
3189 }
3221
3190
3222 #content div.panel div.form div.form-horizontal div.form-group > div {
3191 #content div.panel div.form div.form-horizontal div.form-group > div {
3223 margin: 10px 20px 10px 200px;
3192 margin: 10px 20px 10px 200px;
3224 padding: 0;
3193 padding: 0;
3225 }
3194 }
3226
3195
3227 #content div.panel div.form div.form-horizontal div.form-group > div a:hover,
3196 #content div.panel div.form div.form-horizontal div.form-group > div a:hover,
3228 #content div.panel div.form div.form-horizontal div.form-group > div a.ui-selectmenu:hover,
3197 #content div.panel div.form div.form-horizontal div.form-group > div a.ui-selectmenu:hover,
3229 #content div.panel div.action a:hover {
3198 #content div.panel div.action a:hover {
3230 color: #000;
3199 color: #000;
3231 text-decoration: none;
3200 text-decoration: none;
3232 }
3201 }
3233
3202
3234 #content div.panel div.form div.form-horizontal div.form-group > div a.ui-selectmenu-focus,
3203 #content div.panel div.form div.form-horizontal div.form-group > div a.ui-selectmenu-focus,
3235 #content div.panel div.action a.ui-selectmenu-focus {
3204 #content div.panel div.action a.ui-selectmenu-focus {
3236 border: 1px solid #666;
3205 border: 1px solid #666;
3237 }
3206 }
3238
3207
3239 #content div.panel div.form div.form-horizontal div.form-group > div div.checkbox {
3208 #content div.panel div.form div.form-horizontal div.form-group > div div.checkbox {
3240 clear: both;
3209 clear: both;
3241 min-height: 12px;
3210 min-height: 12px;
3242 padding: 0;
3211 padding: 0;
3243 margin: 14px 0 10px;
3212 margin: 14px 0 10px;
3244 }
3213 }
3245
3214
3246 #content div.panel div.form div.form-horizontal div.form-group > div div.checkbox input {
3215 #content div.panel div.form div.form-horizontal div.form-group > div div.checkbox input {
3247 float: left;
3216 float: left;
3248 margin: -4px 5px 0px 0px;
3217 margin: -4px 5px 0px 0px;
3249 }
3218 }
3250
3219
3251 div.form div.form-horizontal div.form-group div.button input,
3220 div.form div.form-horizontal div.form-group div.button input,
3252 #content div.panel div.form div.form-horizontal div.buttons input,
3221 #content div.panel div.form div.form-horizontal div.buttons input,
3253 div.form div.form-horizontal div.buttons input,
3222 div.form div.form-horizontal div.buttons input,
3254 #content div.panel div.action div.button input {
3223 #content div.panel div.action div.button input {
3255 font-size: 11px;
3224 font-size: 11px;
3256 font-weight: 700;
3225 font-weight: 700;
3257 margin: 0;
3226 margin: 0;
3258 }
3227 }
3259
3228
3260 div.form div.form-horizontal div.form-group div.highlight,
3229 div.form div.form-horizontal div.form-group div.highlight,
3261 #content div.panel div.form div.form-horizontal div.buttons div.highlight {
3230 #content div.panel div.form div.form-horizontal div.buttons div.highlight {
3262 display: inline;
3231 display: inline;
3263 }
3232 }
3264
3233
3265 #content div.panel div.form div.form-horizontal div.buttons,
3234 #content div.panel div.form div.form-horizontal div.buttons,
3266 div.form div.form-horizontal div.buttons {
3235 div.form div.form-horizontal div.buttons {
3267 margin: 10px 10px 0 200px;
3236 margin: 10px 10px 0 200px;
3268 padding: 0;
3237 padding: 0;
3269 }
3238 }
3270
3239
3271 #content div.panel table td.user,
3240 #content div.panel table td.user,
3272 #content div.panel table td.address {
3241 #content div.panel table td.address {
3273 width: 10%;
3242 width: 10%;
3274 text-align: center;
3243 text-align: center;
3275 }
3244 }
3276
3245
3277 #content div.panel div.action div.button,
3246 #content div.panel div.action div.button,
3278 #login div.form div.form-horizontal div.form-group > div div.link,
3247 #login div.form div.form-horizontal div.form-group > div div.link,
3279 #register div.form div.form-horizontal div.form-group > div div.link {
3248 #register div.form div.form-horizontal div.form-group > div div.link {
3280 text-align: right;
3249 text-align: right;
3281 margin: 6px 0 0;
3250 margin: 6px 0 0;
3282 padding: 0;
3251 padding: 0;
3283 }
3252 }
3284
3253
3285 #login, #register {
3254 #login, #register {
3286 width: 520px;
3255 width: 520px;
3287 margin: 10% auto 0;
3256 margin: 10% auto 0;
3288 padding: 0;
3257 padding: 0;
3289 }
3258 }
3290
3259
3291 #login div.color,
3260 #login div.color,
3292 #register div.color {
3261 #register div.color {
3293 clear: both;
3262 clear: both;
3294 overflow: hidden;
3263 overflow: hidden;
3295 background: #FFF;
3264 background: #FFF;
3296 margin: 10px auto 0;
3265 margin: 10px auto 0;
3297 padding: 3px 3px 3px 0;
3266 padding: 3px 3px 3px 0;
3298 }
3267 }
3299
3268
3300 #login div.color a,
3269 #login div.color a,
3301 #register div.color a {
3270 #register div.color a {
3302 width: 20px;
3271 width: 20px;
3303 height: 20px;
3272 height: 20px;
3304 display: block;
3273 display: block;
3305 float: left;
3274 float: left;
3306 margin: 0 0 0 3px;
3275 margin: 0 0 0 3px;
3307 padding: 0;
3276 padding: 0;
3308 }
3277 }
3309
3278
3310 #login div.panel-heading h5,
3279 #login div.panel-heading h5,
3311 #register div.panel-heading h5 {
3280 #register div.panel-heading h5 {
3312 color: #fff;
3281 color: #fff;
3313 margin: 10px;
3282 margin: 10px;
3314 padding: 0;
3283 padding: 0;
3315 }
3284 }
3316
3285
3317 #login div.form div.form-horizontal div.form-group,
3286 #login div.form div.form-horizontal div.form-group,
3318 #register div.form div.form-horizontal div.form-group {
3287 #register div.form div.form-horizontal div.form-group {
3319 clear: both;
3288 clear: both;
3320 overflow: hidden;
3289 overflow: hidden;
3321 margin: 0;
3290 margin: 0;
3322 padding: 0 0 10px;
3291 padding: 0 0 10px;
3323 }
3292 }
3324
3293
3325 #login div.form div.form-horizontal div.form-group span.error-message,
3294 #login div.form div.form-horizontal div.form-group span.error-message,
3326 #register div.form div.form-horizontal div.form-group span.error-message {
3295 #register div.form div.form-horizontal div.form-group span.error-message {
3327 height: 1%;
3296 height: 1%;
3328 display: block;
3297 display: block;
3329 color: red;
3298 color: red;
3330 margin: 8px 0 0;
3299 margin: 8px 0 0;
3331 padding: 0;
3300 padding: 0;
3332 max-width: 320px;
3301 max-width: 320px;
3333 }
3302 }
3334
3303
3335 #login div.form div.form-horizontal div.form-group label,
3304 #login div.form div.form-horizontal div.form-group label,
3336 #register div.form div.form-horizontal div.form-group > label {
3305 #register div.form div.form-horizontal div.form-group > label {
3337 color: #000;
3306 color: #000;
3338 font-weight: 700;
3307 font-weight: 700;
3339 }
3308 }
3340
3309
3341 #login div.form div.form-horizontal div.form-group div,
3310 #login div.form div.form-horizontal div.form-group div,
3342 #register div.form div.form-horizontal div.form-group > div {
3311 #register div.form div.form-horizontal div.form-group > div {
3343 float: left;
3312 float: left;
3344 margin: 0;
3313 margin: 0;
3345 padding: 0;
3314 padding: 0;
3346 }
3315 }
3347
3316
3348 #login div.form div.form-horizontal div.form-group div.checkbox,
3317 #login div.form div.form-horizontal div.form-group div.checkbox,
3349 #register div.form div.form-horizontal div.form-group div.checkbox {
3318 #register div.form div.form-horizontal div.form-group div.checkbox {
3350 margin: 0 0 0 184px;
3319 margin: 0 0 0 184px;
3351 padding: 0;
3320 padding: 0;
3352 }
3321 }
3353
3322
3354 #login div.form div.form-horizontal div.form-group div.checkbox label,
3323 #login div.form div.form-horizontal div.form-group div.checkbox label,
3355 #register div.form div.form-horizontal div.form-group div.checkbox label {
3324 #register div.form div.form-horizontal div.form-group div.checkbox label {
3356 color: #565656;
3325 color: #565656;
3357 font-weight: 700;
3326 font-weight: 700;
3358 }
3327 }
3359
3328
3360 #login div.form div.buttons input,
3329 #login div.form div.buttons input,
3361 #register div.form div.form-horizontal div.buttons input {
3330 #register div.form div.form-horizontal div.buttons input {
3362 color: #000;
3331 color: #000;
3363 font-size: 1em;
3332 font-size: 1em;
3364 font-weight: 700;
3333 font-weight: 700;
3365 margin: 0;
3334 margin: 0;
3366 }
3335 }
3367
3336
3368 #changeset_content .container .wrapper,
3337 #changeset_content .container .wrapper,
3369 #graph_content .container .wrapper {
3338 #graph_content .container .wrapper {
3370 width: 600px;
3339 width: 600px;
3371 }
3340 }
3372
3341
3373 #changeset_content .container .date,
3342 #changeset_content .container .date,
3374 .ac .match {
3343 .ac .match {
3375 font-weight: 700;
3344 font-weight: 700;
3376 padding-top: 5px;
3345 padding-top: 5px;
3377 padding-bottom: 5px;
3346 padding-bottom: 5px;
3378 }
3347 }
3379
3348
3380 div#legend_container table td,
3349 div#legend_container table td,
3381 div#legend_choices table td {
3350 div#legend_choices table td {
3382 border: none !important;
3351 border: none !important;
3383 height: 20px !important;
3352 height: 20px !important;
3384 padding: 0 !important;
3353 padding: 0 !important;
3385 }
3354 }
3386
3355
3387 .q_filter_box {
3356 .q_filter_box {
3388 border-radius: 4px;
3357 border-radius: 4px;
3389 border: 0 none;
3358 border: 0 none;
3390 margin-bottom: -4px;
3359 margin-bottom: -4px;
3391 margin-top: -4px;
3360 margin-top: -4px;
3392 padding-left: 3px;
3361 padding-left: 3px;
3393 }
3362 }
3394
3363
3395 #node_filter {
3364 #node_filter {
3396 border: 0px solid #545454;
3365 border: 0px solid #545454;
3397 color: #AAAAAA;
3366 color: #AAAAAA;
3398 padding-left: 3px;
3367 padding-left: 3px;
3399 }
3368 }
3400
3369
3401 .reviewer_status {
3370 .reviewer_status {
3402 float: left;
3371 float: left;
3403 }
3372 }
3404
3373
3405 .reviewers_member {
3374 .reviewers_member {
3406 height: 15px;
3375 height: 15px;
3407 padding: 0px 0px 0px 10px;
3376 padding: 0px 0px 0px 10px;
3408 }
3377 }
3409
3378
3410 .emails_wrap .email_entry {
3379 .emails_wrap .email_entry {
3411 height: 30px;
3380 height: 30px;
3412 padding: 0px 0px 0px 10px;
3381 padding: 0px 0px 0px 10px;
3413 }
3382 }
3414 .emails_wrap .email_entry .email {
3383 .emails_wrap .email_entry .email {
3415 float: left
3384 float: left
3416 }
3385 }
3417 .emails_wrap .email_entry .email_action {
3386 .emails_wrap .email_entry .email_action {
3418 float: left
3387 float: left
3419 }
3388 }
3420
3389
3421 .ips_wrap .ip_entry {
3390 .ips_wrap .ip_entry {
3422 height: 30px;
3391 height: 30px;
3423 padding: 0px 0px 0px 10px;
3392 padding: 0px 0px 0px 10px;
3424 }
3393 }
3425 .ips_wrap .ip_entry .ip {
3394 .ips_wrap .ip_entry .ip {
3426 float: left
3395 float: left
3427 }
3396 }
3428 .ips_wrap .ip_entry .ip_action {
3397 .ips_wrap .ip_entry .ip_action {
3429 float: left
3398 float: left
3430 }
3399 }
3431
3400
3432
3401
3433 /*README STYLE*/
3402 /*README STYLE*/
3434
3403
3435 div.readme {
3404 div.readme {
3436 padding: 0px;
3405 padding: 0px;
3437 }
3406 }
3438
3407
3439 div.readme h2 {
3408 div.readme h2 {
3440 font-weight: normal;
3409 font-weight: normal;
3441 }
3410 }
3442
3411
3443 div.readme .readme_box {
3412 div.readme .readme_box {
3444 background-color: #fafafa;
3413 background-color: #fafafa;
3445 }
3414 }
3446
3415
3447 div.readme .readme_box {
3416 div.readme .readme_box {
3448 clear: both;
3417 clear: both;
3449 overflow: hidden;
3418 overflow: hidden;
3450 margin: 0;
3419 margin: 0;
3451 padding: 0 20px 10px;
3420 padding: 0 20px 10px;
3452 }
3421 }
3453
3422
3454 div.readme .readme_box h1,
3423 div.readme .readme_box h1,
3455 div.readme .readme_box h2,
3424 div.readme .readme_box h2,
3456 div.readme .readme_box h3,
3425 div.readme .readme_box h3,
3457 div.readme .readme_box h4,
3426 div.readme .readme_box h4,
3458 div.readme .readme_box h5,
3427 div.readme .readme_box h5,
3459 div.readme .readme_box h6 {
3428 div.readme .readme_box h6 {
3460 border-bottom: 0 !important;
3429 border-bottom: 0 !important;
3461 margin: 0 !important;
3430 margin: 0 !important;
3462 padding: 0 !important;
3431 padding: 0 !important;
3463 line-height: 1.5em !important;
3432 line-height: 1.5em !important;
3464 }
3433 }
3465
3434
3466
3435
3467 div.readme .readme_box h1:first-child {
3436 div.readme .readme_box h1:first-child {
3468 padding-top: .25em !important;
3437 padding-top: .25em !important;
3469 }
3438 }
3470
3439
3471 div.readme .readme_box h2,
3440 div.readme .readme_box h2,
3472 div.readme .readme_box h3 {
3441 div.readme .readme_box h3 {
3473 margin: 1em 0 !important;
3442 margin: 1em 0 !important;
3474 }
3443 }
3475
3444
3476 div.readme .readme_box h2 {
3445 div.readme .readme_box h2 {
3477 margin-top: 1.5em !important;
3446 margin-top: 1.5em !important;
3478 border-top: 4px solid #e0e0e0 !important;
3447 border-top: 4px solid #e0e0e0 !important;
3479 padding-top: .5em !important;
3448 padding-top: .5em !important;
3480 }
3449 }
3481
3450
3482 div.readme .readme_box p {
3451 div.readme .readme_box p {
3483 color: black !important;
3452 color: black !important;
3484 margin: 1em 0 !important;
3453 margin: 1em 0 !important;
3485 line-height: 1.5em !important;
3454 line-height: 1.5em !important;
3486 }
3455 }
3487
3456
3488 div.readme .readme_box ul {
3457 div.readme .readme_box ul {
3489 list-style: disc !important;
3458 list-style: disc !important;
3490 margin: 1em 0 1em 2em !important;
3459 margin: 1em 0 1em 2em !important;
3491 }
3460 }
3492
3461
3493 div.readme .readme_box ol {
3462 div.readme .readme_box ol {
3494 list-style: decimal;
3463 list-style: decimal;
3495 margin: 1em 0 1em 2em !important;
3464 margin: 1em 0 1em 2em !important;
3496 }
3465 }
3497
3466
3498 div.readme .readme_box code {
3467 div.readme .readme_box code {
3499 font-size: 12px !important;
3468 font-size: 12px !important;
3500 background-color: ghostWhite !important;
3469 background-color: ghostWhite !important;
3501 color: #444 !important;
3470 color: #444 !important;
3502 padding: 0 .2em !important;
3471 padding: 0 .2em !important;
3503 border: 1px solid #dedede !important;
3472 border: 1px solid #dedede !important;
3504 }
3473 }
3505
3474
3506 div.readme .readme_box pre code {
3475 div.readme .readme_box pre code {
3507 padding: 0 !important;
3476 padding: 0 !important;
3508 font-size: 12px !important;
3477 font-size: 12px !important;
3509 background-color: #eee !important;
3478 background-color: #eee !important;
3510 border: none !important;
3479 border: none !important;
3511 }
3480 }
3512
3481
3513 div.readme .readme_box pre {
3482 div.readme .readme_box pre {
3514 margin: 1em 0;
3483 margin: 1em 0;
3515 font-size: 12px;
3484 font-size: 12px;
3516 background-color: #eee;
3485 background-color: #eee;
3517 border: 1px solid #ddd;
3486 border: 1px solid #ddd;
3518 padding: 5px;
3487 padding: 5px;
3519 color: #444;
3488 color: #444;
3520 overflow: auto;
3489 overflow: auto;
3521 border-radius: 3px;
3490 border-radius: 3px;
3522 }
3491 }
3523
3492
3524 div.readme .readme_box table {
3493 div.readme .readme_box table {
3525 display: table;
3494 display: table;
3526 border-collapse: separate;
3495 border-collapse: separate;
3527 border-spacing: 2px;
3496 border-spacing: 2px;
3528 border-color: gray;
3497 border-color: gray;
3529 width: auto !important;
3498 width: auto !important;
3530 }
3499 }
3531
3500
3532
3501
3533 /** RST STYLE **/
3502 /** RST STYLE **/
3534
3503
3535
3504
3536 div.rst-block {
3505 div.rst-block {
3537 padding: 0px;
3506 padding: 0px;
3538 }
3507 }
3539
3508
3540 div.rst-block h2 {
3509 div.rst-block h2 {
3541 font-weight: normal;
3510 font-weight: normal;
3542 }
3511 }
3543
3512
3544 div.rst-block {
3513 div.rst-block {
3545 background-color: #fafafa;
3514 background-color: #fafafa;
3546 }
3515 }
3547
3516
3548 div.rst-block {
3517 div.rst-block {
3549 clear: both;
3518 clear: both;
3550 overflow: hidden;
3519 overflow: hidden;
3551 margin: 0;
3520 margin: 0;
3552 padding: 0 20px;
3521 padding: 0 20px;
3553 }
3522 }
3554
3523
3555 div.rst-block h1,
3524 div.rst-block h1,
3556 div.rst-block h2,
3525 div.rst-block h2,
3557 div.rst-block h3,
3526 div.rst-block h3,
3558 div.rst-block h4,
3527 div.rst-block h4,
3559 div.rst-block h5,
3528 div.rst-block h5,
3560 div.rst-block h6 {
3529 div.rst-block h6 {
3561 border-bottom: 0 !important;
3530 border-bottom: 0 !important;
3562 margin: 0 !important;
3531 margin: 0 !important;
3563 padding: 0 !important;
3532 padding: 0 !important;
3564 line-height: 1.5em !important;
3533 line-height: 1.5em !important;
3565 }
3534 }
3566
3535
3567
3536
3568 div.rst-block h1:first-child {
3537 div.rst-block h1:first-child {
3569 padding-top: .25em !important;
3538 padding-top: .25em !important;
3570 }
3539 }
3571
3540
3572 div.rst-block h2,
3541 div.rst-block h2,
3573 div.rst-block h3 {
3542 div.rst-block h3 {
3574 margin: 1em 0 !important;
3543 margin: 1em 0 !important;
3575 }
3544 }
3576
3545
3577 div.rst-block h2 {
3546 div.rst-block h2 {
3578 margin-top: 1.5em !important;
3547 margin-top: 1.5em !important;
3579 border-top: 4px solid #e0e0e0 !important;
3548 border-top: 4px solid #e0e0e0 !important;
3580 padding-top: .5em !important;
3549 padding-top: .5em !important;
3581 }
3550 }
3582
3551
3583 div.rst-block p {
3552 div.rst-block p {
3584 color: black !important;
3553 color: black !important;
3585 margin: 1em 0 !important;
3554 margin: 1em 0 !important;
3586 line-height: 1.5em !important;
3555 line-height: 1.5em !important;
3587 }
3556 }
3588
3557
3589 div.rst-block ul {
3558 div.rst-block ul {
3590 list-style: disc !important;
3559 list-style: disc !important;
3591 margin: 1em 0 1em 2em !important;
3560 margin: 1em 0 1em 2em !important;
3592 }
3561 }
3593
3562
3594 div.rst-block ol {
3563 div.rst-block ol {
3595 list-style: decimal;
3564 list-style: decimal;
3596 margin: 1em 0 1em 2em !important;
3565 margin: 1em 0 1em 2em !important;
3597 }
3566 }
3598
3567
3599 div.rst-block code {
3568 div.rst-block code {
3600 font-size: 12px !important;
3569 font-size: 12px !important;
3601 background-color: ghostWhite !important;
3570 background-color: ghostWhite !important;
3602 color: #444 !important;
3571 color: #444 !important;
3603 padding: 0 .2em !important;
3572 padding: 0 .2em !important;
3604 border: 1px solid #dedede !important;
3573 border: 1px solid #dedede !important;
3605 }
3574 }
3606
3575
3607 div.rst-block pre code {
3576 div.rst-block pre code {
3608 padding: 0 !important;
3577 padding: 0 !important;
3609 font-size: 12px !important;
3578 font-size: 12px !important;
3610 background-color: #eee !important;
3579 background-color: #eee !important;
3611 border: none !important;
3580 border: none !important;
3612 }
3581 }
3613
3582
3614 div.rst-block pre {
3583 div.rst-block pre {
3615 margin: 1em 0;
3584 margin: 1em 0;
3616 font-size: 12px;
3585 font-size: 12px;
3617 background-color: #eee;
3586 background-color: #eee;
3618 border: 1px solid #ddd;
3587 border: 1px solid #ddd;
3619 padding: 5px;
3588 padding: 5px;
3620 color: #444;
3589 color: #444;
3621 overflow: auto;
3590 overflow: auto;
3622 border-radius: 3px;
3591 border-radius: 3px;
3623 }
3592 }
3624
3593
3625
3594
3626 /** comment main **/
3595 /** comment main **/
3627 .comments {
3596 .comments {
3628 padding: 10px 20px;
3597 padding: 10px 20px;
3629 max-width: 978px;
3598 max-width: 978px;
3630 }
3599 }
3631
3600
3632 .comments .comment .comment-wrapp {
3601 .comments .comment .comment-wrapp {
3633 border: 1px solid #ddd;
3602 border: 1px solid #ddd;
3634 margin-top: 10px;
3603 margin-top: 10px;
3635 border-radius: 4px;
3604 border-radius: 4px;
3636 }
3605 }
3637
3606
3638 .comments .comment .meta {
3607 .comments .comment .meta {
3639 background: #f8f8f8;
3608 background: #f8f8f8;
3640 padding: 4px;
3609 padding: 4px;
3641 border-bottom: 1px solid #ddd;
3610 border-bottom: 1px solid #ddd;
3642 min-height: 18px;
3611 min-height: 18px;
3643 overflow: auto;
3612 overflow: auto;
3644 }
3613 }
3645
3614
3646 .comments .comment .meta img {
3615 .comments .comment .meta img {
3647 vertical-align: middle;
3616 vertical-align: middle;
3648 }
3617 }
3649
3618
3650 .comments .comment .meta .user {
3619 .comments .comment .meta .user {
3651 font-weight: bold;
3620 font-weight: bold;
3652 float: left;
3621 float: left;
3653 padding: 4px 2px 2px 2px;
3622 padding: 4px 2px 2px 2px;
3654 }
3623 }
3655
3624
3656 .comments .comment .meta .date {
3625 .comments .comment .meta .date {
3657 float: left;
3626 float: left;
3658 padding: 4px 4px 0px 4px;
3627 padding: 4px 4px 0px 4px;
3659 }
3628 }
3660
3629
3661 .comments .comment .text {
3630 .comments .comment .text {
3662 background-color: #FAFAFA;
3631 background-color: #FAFAFA;
3663 margin: 6px;
3632 margin: 6px;
3664 }
3633 }
3665
3634
3666 .comments-number {
3635 .comments-number {
3667 padding: 0px 20px 10px;
3636 padding: 0px 20px 10px;
3668 font-weight: bold;
3637 font-weight: bold;
3669 color: #666;
3638 color: #666;
3670 font-size: 16px;
3639 font-size: 16px;
3671 }
3640 }
3672
3641
3673 .automatic-comment {
3642 .automatic-comment {
3674 font-style: italic;
3643 font-style: italic;
3675 }
3644 }
3676
3645
3677 /** comment form **/
3646 /** comment form **/
3678
3647
3679 .status-block {
3648 .status-block {
3680 margin: 5px;
3649 margin: 5px;
3681 clear: both
3650 clear: both
3682 }
3651 }
3683
3652
3684 .comment-form textarea {
3653 .comment-form textarea {
3685 width: 100%;
3654 width: 100%;
3686 height: 100px;
3655 height: 100px;
3687 font-family: Lucida Console, Consolas, Monaco, Inconsolata, Liberation Mono, monospace;
3656 font-family: Lucida Console, Consolas, Monaco, Inconsolata, Liberation Mono, monospace;
3688 }
3657 }
3689
3658
3690 form.comment-form {
3659 form.comment-form {
3691 margin-top: 10px;
3660 margin-top: 10px;
3692 margin-left: 10px;
3661 margin-left: 10px;
3693 }
3662 }
3694
3663
3695 .comment-inline-form .comment-block-ta,
3664 .comment-inline-form .comment-block-ta,
3696 .comment-form .comment-block-ta {
3665 .comment-form .comment-block-ta {
3697 border: 1px solid #ccc;
3666 border: 1px solid #ccc;
3698 border-radius: 3px;
3667 border-radius: 3px;
3699 box-sizing: border-box;
3668 box-sizing: border-box;
3700 }
3669 }
3701
3670
3702 .comment-form-submit {
3671 .comment-form-submit {
3703 margin-top: 5px;
3672 margin-top: 5px;
3704 margin-left: 525px;
3673 margin-left: 525px;
3705 }
3674 }
3706
3675
3707 .file-comments {
3676 .file-comments {
3708 display: none;
3677 display: none;
3709 }
3678 }
3710
3679
3711 .comment-form .comment {
3680 .comment-form .comment {
3712 margin-left: 10px;
3681 margin-left: 10px;
3713 }
3682 }
3714
3683
3715 .comment-form .comment-help {
3684 .comment-form .comment-help {
3716 padding: 5px 5px 5px 5px;
3685 padding: 5px 5px 5px 5px;
3717 color: #666;
3686 color: #666;
3718 }
3687 }
3719
3688
3720 .comment-form .comment-button {
3689 .comment-form .comment-button {
3721 padding-top: 5px;
3690 padding-top: 5px;
3722 }
3691 }
3723
3692
3724 .add-another-button {
3693 .add-another-button {
3725 margin-left: 10px;
3694 margin-left: 10px;
3726 margin-top: 10px;
3695 margin-top: 10px;
3727 margin-bottom: 10px;
3696 margin-bottom: 10px;
3728 }
3697 }
3729
3698
3730 .comment .buttons {
3699 .comment .buttons {
3731 float: right;
3700 float: right;
3732 margin: -1px 0px 0px 0px;
3701 margin: -1px 0px 0px 0px;
3733 }
3702 }
3734
3703
3735 .show-inline-comments {
3704 .show-inline-comments {
3736 position: relative;
3705 position: relative;
3737 top: 1px
3706 top: 1px
3738 }
3707 }
3739
3708
3740 /** comment inline form **/
3709 /** comment inline form **/
3741 .comment-inline-form {
3710 .comment-inline-form {
3742 margin: 4px;
3711 margin: 4px;
3743 max-width: 978px;
3712 max-width: 978px;
3744 }
3713 }
3745 .comment-inline-form .submitting-overlay {
3714 .comment-inline-form .submitting-overlay {
3746 display: none;
3715 display: none;
3747 height: 0;
3716 height: 0;
3748 text-align: center;
3717 text-align: center;
3749 font-size: 16px;
3718 font-size: 16px;
3750 opacity: 0.5;
3719 opacity: 0.5;
3751 }
3720 }
3752
3721
3753 .comment-inline-form .clearfix,
3722 .comment-inline-form .clearfix,
3754 .comment-form .clearfix {
3723 .comment-form .clearfix {
3755 background: #EEE;
3724 background: #EEE;
3756 border-radius: 4px;
3725 border-radius: 4px;
3757 padding: 5px;
3726 padding: 5px;
3758 margin: 0px;
3727 margin: 0px;
3759 }
3728 }
3760
3729
3761 div.comment-inline-form {
3730 div.comment-inline-form {
3762 padding: 4px 0px 6px 0px;
3731 padding: 4px 0px 6px 0px;
3763 }
3732 }
3764
3733
3765 .comment-inline-form textarea {
3734 .comment-inline-form textarea {
3766 width: 100%;
3735 width: 100%;
3767 height: 100px;
3736 height: 100px;
3768 font-family: Lucida Console, Consolas, Monaco, Inconsolata, Liberation Mono, monospace;
3737 font-family: Lucida Console, Consolas, Monaco, Inconsolata, Liberation Mono, monospace;
3769 }
3738 }
3770
3739
3771 form.comment-inline-form {
3740 form.comment-inline-form {
3772 margin-top: 10px;
3741 margin-top: 10px;
3773 margin-left: 10px;
3742 margin-left: 10px;
3774 }
3743 }
3775
3744
3776 .comment-inline-form-submit {
3745 .comment-inline-form-submit {
3777 margin-top: 5px;
3746 margin-top: 5px;
3778 margin-left: 525px;
3747 margin-left: 525px;
3779 }
3748 }
3780
3749
3781 .file-comments {
3750 .file-comments {
3782 display: none;
3751 display: none;
3783 }
3752 }
3784
3753
3785 .comment-inline-form .comment {
3754 .comment-inline-form .comment {
3786 margin-left: 10px;
3755 margin-left: 10px;
3787 }
3756 }
3788
3757
3789 .comment-inline-form .comment-help {
3758 .comment-inline-form .comment-help {
3790 padding: 5px 5px 5px 5px;
3759 padding: 5px 5px 5px 5px;
3791 color: #666;
3760 color: #666;
3792 }
3761 }
3793
3762
3794 .comment-inline-form .comment-button {
3763 .comment-inline-form .comment-button {
3795 padding-top: 5px;
3764 padding-top: 5px;
3796 }
3765 }
3797
3766
3798 /** comment inline **/
3767 /** comment inline **/
3799 .inline-comments {
3768 .inline-comments {
3800 padding: 0 20px;
3769 padding: 0 20px;
3801 }
3770 }
3802
3771
3803 .inline-comments .comment .comment-wrapp {
3772 .inline-comments .comment .comment-wrapp {
3804 max-width: 978px;
3773 max-width: 978px;
3805 border: 1px solid #ddd;
3774 border: 1px solid #ddd;
3806 border-radius: 4px;
3775 border-radius: 4px;
3807 margin: 3px 3px 5px 5px;
3776 margin: 3px 3px 5px 5px;
3808 background-color: #FAFAFA;
3777 background-color: #FAFAFA;
3809 }
3778 }
3810
3779
3811 .inline-comments .add-button-row {
3780 .inline-comments .add-button-row {
3812 padding: 2px 4px 8px 5px;
3781 padding: 2px 4px 8px 5px;
3813 }
3782 }
3814
3783
3815 .inline-comments .comment .meta {
3784 .inline-comments .comment .meta {
3816 background: #f8f8f8;
3785 background: #f8f8f8;
3817 padding: 4px;
3786 padding: 4px;
3818 border-bottom: 1px solid #ddd;
3787 border-bottom: 1px solid #ddd;
3819 min-height: 20px;
3788 min-height: 20px;
3820 overflow: auto;
3789 overflow: auto;
3821 }
3790 }
3822
3791
3823 .inline-comments .comment .meta img {
3792 .inline-comments .comment .meta img {
3824 vertical-align: middle;
3793 vertical-align: middle;
3825 }
3794 }
3826
3795
3827 .inline-comments .comment .meta .user {
3796 .inline-comments .comment .meta .user {
3828 font-weight: bold;
3797 font-weight: bold;
3829 float: left;
3798 float: left;
3830 padding: 3px;
3799 padding: 3px;
3831 }
3800 }
3832
3801
3833 .inline-comments .comment .meta .date {
3802 .inline-comments .comment .meta .date {
3834 float: left;
3803 float: left;
3835 padding: 3px;
3804 padding: 3px;
3836 }
3805 }
3837
3806
3838 .inline-comments .comment .text {
3807 .inline-comments .comment .text {
3839 background-color: #FAFAFA;
3808 background-color: #FAFAFA;
3840 margin: 6px;
3809 margin: 6px;
3841 }
3810 }
3842
3811
3843 .inline-comments .comments-number {
3812 .inline-comments .comments-number {
3844 padding: 0px 0px 10px 0px;
3813 padding: 0px 0px 10px 0px;
3845 font-weight: bold;
3814 font-weight: bold;
3846 color: #666;
3815 color: #666;
3847 font-size: 16px;
3816 font-size: 16px;
3848 }
3817 }
3849
3818
3850 input.status_change_radio {
3819 input.status_change_radio {
3851 margin: 2px 0 5px 15px;
3820 margin: 2px 0 5px 15px;
3852 vertical-align: middle;
3821 vertical-align: middle;
3853 }
3822 }
3854
3823
3855 .badge {
3824 .badge {
3856 padding: 4px 4px !important;
3825 padding: 4px 4px !important;
3857 text-align: center;
3826 text-align: center;
3858 color: #888 !important;
3827 color: #888 !important;
3859 background-color: #DEDEDE !important;
3828 background-color: #DEDEDE !important;
3860 border-radius: 4px !important;
3829 border-radius: 4px !important;
3861 }
3830 }
3862
3831
3863 .notification-header {
3832 .notification-header {
3864 padding-top: 6px;
3833 padding-top: 6px;
3865 }
3834 }
3866 .notification-header .desc {
3835 .notification-header .desc {
3867 font-size: 16px;
3836 font-size: 16px;
3868 height: 24px;
3837 height: 24px;
3869 float: left
3838 float: left
3870 }
3839 }
3871 .notification-list .container.unread {
3840 .notification-list .container.unread {
3872 background: none repeat scroll 0 0 rgba(255, 255, 180, 0.6);
3841 background: none repeat scroll 0 0 rgba(255, 255, 180, 0.6);
3873 }
3842 }
3874 .notification-header .gravatar {
3843 .notification-header .gravatar {
3875 background: none repeat scroll 0 0 transparent;
3844 background: none repeat scroll 0 0 transparent;
3876 padding: 0px 0px 0px 8px;
3845 padding: 0px 0px 0px 8px;
3877 }
3846 }
3878 .notification-list .container .notification-header .desc {
3847 .notification-list .container .notification-header .desc {
3879 font-weight: bold;
3848 font-weight: bold;
3880 font-size: 17px;
3849 font-size: 17px;
3881 }
3850 }
3882 .notification-header .delete-notifications {
3851 .notification-header .delete-notifications {
3883 float: right;
3852 float: right;
3884 padding-top: 8px;
3853 padding-top: 8px;
3885 cursor: pointer;
3854 cursor: pointer;
3886 }
3855 }
3887 .notification-header .read-notifications {
3856 .notification-header .read-notifications {
3888 float: right;
3857 float: right;
3889 padding-top: 8px;
3858 padding-top: 8px;
3890 cursor: pointer;
3859 cursor: pointer;
3891 }
3860 }
3892 .notification-subject {
3861 .notification-subject {
3893 clear: both;
3862 clear: both;
3894 border-bottom: 1px solid #eee;
3863 border-bottom: 1px solid #eee;
3895 padding: 5px 0px;
3864 padding: 5px 0px;
3896 }
3865 }
3897
3866
3898 .notification-body {
3867 .notification-body {
3899 clear: both;
3868 clear: both;
3900 margin: 34px 2px 2px 8px
3869 margin: 34px 2px 2px 8px
3901 }
3870 }
3902
3871
3903 /****
3872 /****
3904 PULL REQUESTS
3873 PULL REQUESTS
3905 *****/
3874 *****/
3906 .pullrequests_section_head {
3875 .pullrequests_section_head {
3907 padding: 10px 10px 10px 0px;
3876 padding: 10px 10px 10px 0px;
3908 margin: 0 20px;
3877 margin: 0 20px;
3909 font-size: 16px;
3878 font-size: 16px;
3910 font-weight: bold;
3879 font-weight: bold;
3911 }
3880 }
3912
3881
3913 div.pr-details-title.closed {
3882 div.pr-details-title.closed {
3914 color: #555;
3883 color: #555;
3915 background: #eee;
3884 background: #eee;
3916 }
3885 }
3917
3886
3918 div.pr {
3887 div.pr {
3919 margin: 0px 20px;
3888 margin: 0px 20px;
3920 padding: 4px 4px;
3889 padding: 4px 4px;
3921 }
3890 }
3922 div.pr-desc {
3891 div.pr-desc {
3923 margin: 0px 20px;
3892 margin: 0px 20px;
3924 }
3893 }
3925 tr.pr-closed td {
3894 tr.pr-closed td {
3926 background-color: #eee !important;
3895 background-color: #eee !important;
3927 color: #555 !important;
3896 color: #555 !important;
3928 }
3897 }
3929
3898
3930 span.pr-closed-tag {
3899 span.pr-closed-tag {
3931 margin-bottom: 1px;
3900 margin-bottom: 1px;
3932 margin-right: 1px;
3901 margin-right: 1px;
3933 padding: 1px 3px;
3902 padding: 1px 3px;
3934 font-size: 10px;
3903 font-size: 10px;
3935 padding: 1px 3px 1px 3px;
3904 padding: 1px 3px 1px 3px;
3936 font-size: 10px;
3905 font-size: 10px;
3937 color: #577632;
3906 color: #577632;
3938 white-space: nowrap;
3907 white-space: nowrap;
3939 border-radius: 4px;
3908 border-radius: 4px;
3940 border: 1px solid #d9e8f8;
3909 border: 1px solid #d9e8f8;
3941 line-height: 1.5em;
3910 line-height: 1.5em;
3942 }
3911 }
3943
3912
3944 .pr-box {
3913 .pr-box {
3945 max-width: 978px;
3914 max-width: 978px;
3946 }
3915 }
3947
3916
3948 #s2id_org_ref,
3917 #s2id_org_ref,
3949 #s2id_other_ref,
3918 #s2id_other_ref,
3950 #s2id_org_repo,
3919 #s2id_org_repo,
3951 #s2id_other_repo {
3920 #s2id_other_repo {
3952 min-width: 150px;
3921 min-width: 150px;
3953 margin: 5px;
3922 margin: 5px;
3954 }
3923 }
3955
3924
3956 #pr-summary .msg-div {
3925 #pr-summary .msg-div {
3957 margin: 5px 0;
3926 margin: 5px 0;
3958 }
3927 }
3959
3928
3960 /****
3929 /****
3961 PERMS
3930 PERMS
3962 *****/
3931 *****/
3963 #perms .perms_section_head {
3932 #perms .perms_section_head {
3964 padding: 10px 10px 10px 0px;
3933 padding: 10px 10px 10px 0px;
3965 font-size: 16px;
3934 font-size: 16px;
3966 font-weight: bold;
3935 font-weight: bold;
3967 text-transform: capitalize;
3936 text-transform: capitalize;
3968 }
3937 }
3969
3938
3970 #perms .perms_section_head label {
3939 #perms .perms_section_head label {
3971 margin-left: 10px;
3940 margin-left: 10px;
3972 }
3941 }
3973
3942
3974 #perms .perm_tag {
3943 #perms .perm_tag {
3975 position: relative;
3944 position: relative;
3976 top: -2px;
3945 top: -2px;
3977 padding: 3px 3px 1px 3px;
3946 padding: 3px 3px 1px 3px;
3978 font-size: 10px;
3947 font-size: 10px;
3979 font-weight: bold;
3948 font-weight: bold;
3980 text-transform: uppercase;
3949 text-transform: uppercase;
3981 white-space: nowrap;
3950 white-space: nowrap;
3982 border-radius: 3px;
3951 border-radius: 3px;
3983 }
3952 }
3984
3953
3985 #perms .perm_tag.admin {
3954 #perms .perm_tag.admin {
3986 background-color: #B94A48;
3955 background-color: #B94A48;
3987 color: #ffffff;
3956 color: #ffffff;
3988 }
3957 }
3989
3958
3990 #perms .perm_tag.write {
3959 #perms .perm_tag.write {
3991 background-color: #DB7525;
3960 background-color: #DB7525;
3992 color: #ffffff;
3961 color: #ffffff;
3993 }
3962 }
3994
3963
3995 #perms .perm_tag.read {
3964 #perms .perm_tag.read {
3996 background-color: #468847;
3965 background-color: #468847;
3997 color: #ffffff;
3966 color: #ffffff;
3998 }
3967 }
3999
3968
4000 #perms .perm_tag.none {
3969 #perms .perm_tag.none {
4001 background-color: #bfbfbf;
3970 background-color: #bfbfbf;
4002 color: #ffffff;
3971 color: #ffffff;
4003 }
3972 }
4004
3973
4005 input.perm_filter {
3974 input.perm_filter {
4006 position: relative;
3975 position: relative;
4007 top: 2px;
3976 top: 2px;
4008 }
3977 }
4009
3978
4010 .perm-gravatar {
3979 .perm-gravatar {
4011 vertical-align: middle;
3980 vertical-align: middle;
4012 padding: 2px;
3981 padding: 2px;
4013 }
3982 }
4014 .perm-gravatar-ac {
3983 .perm-gravatar-ac {
4015 vertical-align: middle;
3984 vertical-align: middle;
4016 padding: 2px;
3985 padding: 2px;
4017 width: 14px;
3986 width: 14px;
4018 height: 14px;
3987 height: 14px;
4019 }
3988 }
4020
3989
4021 /*****************************************************************************
3990 /*****************************************************************************
4022 DIFFS CSS
3991 DIFFS CSS
4023 ******************************************************************************/
3992 ******************************************************************************/
4024 .diff-collapse {
3993 .diff-collapse {
4025 text-align: center;
3994 text-align: center;
4026 margin-bottom: -15px;
3995 margin-bottom: -15px;
4027 }
3996 }
4028 .diff-collapse-button {
3997 .diff-collapse-button {
4029 cursor: pointer;
3998 cursor: pointer;
4030 color: #666;
3999 color: #666;
4031 font-size: 16px;
4000 font-size: 16px;
4032 }
4001 }
4033 .diff-container {
4002 .diff-container {
4034
4003
4035 }
4004 }
4036
4005
4037 .compare-revision-selector {
4006 .compare-revision-selector {
4038 font-weight: bold;
4007 font-weight: bold;
4039 font-size: 14px;
4008 font-size: 14px;
4040 }
4009 }
4041 .compare-revision-selector > div {
4010 .compare-revision-selector > div {
4042 display: inline-block;
4011 display: inline-block;
4043 margin-left: 8px;
4012 margin-left: 8px;
4044 vertical-align: middle;
4013 vertical-align: middle;
4045 }
4014 }
4046 .compare-revision-selector .btn {
4015 .compare-revision-selector .btn {
4047 margin-bottom: 0;
4016 margin-bottom: 0;
4048 }
4017 }
4049
4018
4050
4019
4051 div.diffblock {
4020 div.diffblock {
4052 overflow: auto;
4021 overflow: auto;
4053 padding: 0px;
4022 padding: 0px;
4054 border: 1px solid #ccc;
4023 border: 1px solid #ccc;
4055 background: #f8f8f8;
4024 background: #f8f8f8;
4056 font-size: 100%;
4025 font-size: 100%;
4057 line-height: 100%;
4026 line-height: 100%;
4058 /* new */
4027 /* new */
4059 line-height: 125%;
4028 line-height: 125%;
4060 border-radius: 6px 6px 0px 0px;
4029 border-radius: 6px 6px 0px 0px;
4061 }
4030 }
4062
4031
4063 .compare-revision-selector,
4032 .compare-revision-selector,
4064 div.diffblock .code-header {
4033 div.diffblock .code-header {
4065 border-bottom: 1px solid #CCCCCC;
4034 border-bottom: 1px solid #CCCCCC;
4066 background: #EEEEEE;
4035 background: #EEEEEE;
4067 padding: 10px 0 10px 0;
4036 padding: 10px 0 10px 0;
4068 min-height: 14px;
4037 min-height: 14px;
4069 }
4038 }
4070
4039
4071 div.diffblock .code-header.banner {
4040 div.diffblock .code-header.banner {
4072 border-bottom: 1px solid #CCCCCC;
4041 border-bottom: 1px solid #CCCCCC;
4073 background: #EEEEEE;
4042 background: #EEEEEE;
4074 height: 14px;
4043 height: 14px;
4075 margin: 0;
4044 margin: 0;
4076 padding: 3px 100px 11px 100px;
4045 padding: 3px 100px 11px 100px;
4077 }
4046 }
4078
4047
4079 div.diffblock .code-header-title {
4048 div.diffblock .code-header-title {
4080 padding: 0px 0px 10px 5px !important;
4049 padding: 0px 0px 10px 5px !important;
4081 margin: 0 !important;
4050 margin: 0 !important;
4082 }
4051 }
4083 div.diffblock .code-header .hash {
4052 div.diffblock .code-header .hash {
4084 float: left;
4053 float: left;
4085 padding: 2px 0 0 2px;
4054 padding: 2px 0 0 2px;
4086 }
4055 }
4087 div.diffblock .code-header .date {
4056 div.diffblock .code-header .date {
4088 float: left;
4057 float: left;
4089 text-transform: uppercase;
4058 text-transform: uppercase;
4090 padding: 2px 0px 0px 2px;
4059 padding: 2px 0px 0px 2px;
4091 }
4060 }
4092 div.diffblock .code-header div {
4061 div.diffblock .code-header div {
4093 margin-left: 4px;
4062 margin-left: 4px;
4094 font-weight: bold;
4063 font-weight: bold;
4095 font-size: 14px;
4064 font-size: 14px;
4096 }
4065 }
4097
4066
4098 div.diffblock .parents {
4067 div.diffblock .parents {
4099 float: left;
4068 float: left;
4100 min-height: 26px;
4069 min-height: 26px;
4101 font-size: 10px;
4070 font-size: 10px;
4102 font-weight: 400;
4071 font-weight: 400;
4103 vertical-align: middle;
4072 vertical-align: middle;
4104 padding: 0px 2px 2px 2px;
4073 padding: 0px 2px 2px 2px;
4105 background-color: #eeeeee;
4074 background-color: #eeeeee;
4106 border-bottom: 1px solid #CCCCCC;
4075 border-bottom: 1px solid #CCCCCC;
4107 }
4076 }
4108
4077
4109 div.diffblock .children {
4078 div.diffblock .children {
4110 float: right;
4079 float: right;
4111 min-height: 26px;
4080 min-height: 26px;
4112 font-size: 10px;
4081 font-size: 10px;
4113 font-weight: 400;
4082 font-weight: 400;
4114 vertical-align: middle;
4083 vertical-align: middle;
4115 text-align: right;
4084 text-align: right;
4116 padding: 0px 2px 2px 2px;
4085 padding: 0px 2px 2px 2px;
4117 background-color: #eeeeee;
4086 background-color: #eeeeee;
4118 border-bottom: 1px solid #CCCCCC;
4087 border-bottom: 1px solid #CCCCCC;
4119 }
4088 }
4120
4089
4121 div.diffblock .code-body {
4090 div.diffblock .code-body {
4122 background: #FFFFFF;
4091 background: #FFFFFF;
4123 clear: both;
4092 clear: both;
4124 }
4093 }
4125 div.diffblock pre.raw {
4094 div.diffblock pre.raw {
4126 background: #FFFFFF;
4095 background: #FFFFFF;
4127 color: #000000;
4096 color: #000000;
4128 }
4097 }
4129 table.code-difftable {
4098 table.code-difftable {
4130 border-collapse: collapse;
4099 border-collapse: collapse;
4131 width: 99%;
4100 width: 99%;
4132 border-radius: 0px !important;
4101 border-radius: 0px !important;
4133 }
4102 }
4134 table.code-difftable td {
4103 table.code-difftable td {
4135 padding: 0 !important;
4104 padding: 0 !important;
4136 background: none !important;
4105 background: none !important;
4137 border: 0 !important;
4106 border: 0 !important;
4138 vertical-align: baseline !important
4107 vertical-align: baseline !important
4139 }
4108 }
4140 table.code-difftable .context {
4109 table.code-difftable .context {
4141 background: none repeat scroll 0 0 #DDE7EF;
4110 background: none repeat scroll 0 0 #DDE7EF;
4142 color: #999;
4111 color: #999;
4143 }
4112 }
4144 table.code-difftable .add {
4113 table.code-difftable .add {
4145 background: none repeat scroll 0 0 #DDFFDD;
4114 background: none repeat scroll 0 0 #DDFFDD;
4146 }
4115 }
4147 table.code-difftable .add ins {
4116 table.code-difftable .add ins {
4148 background: none repeat scroll 0 0 #AAFFAA;
4117 background: none repeat scroll 0 0 #AAFFAA;
4149 text-decoration: none;
4118 text-decoration: none;
4150 }
4119 }
4151 table.code-difftable .del {
4120 table.code-difftable .del {
4152 background: none repeat scroll 0 0 #FFDDDD;
4121 background: none repeat scroll 0 0 #FFDDDD;
4153 }
4122 }
4154 table.code-difftable .del del {
4123 table.code-difftable .del del {
4155 background: none repeat scroll 0 0 #FFAAAA;
4124 background: none repeat scroll 0 0 #FFAAAA;
4156 text-decoration: none;
4125 text-decoration: none;
4157 }
4126 }
4158
4127
4159 table.code-highlighttable div.code-highlight pre u:before,
4128 table.code-highlighttable div.code-highlight pre u:before,
4160 table.code-difftable td.code pre u:before {
4129 table.code-difftable td.code pre u:before {
4161 content: "\21a6";
4130 content: "\21a6";
4162 display: inline-block;
4131 display: inline-block;
4163 width: 0;
4132 width: 0;
4164 }
4133 }
4165 table.code-highlighttable div.code-highlight pre u.cr:before,
4134 table.code-highlighttable div.code-highlight pre u.cr:before,
4166 table.code-difftable td.code pre u.cr:before {
4135 table.code-difftable td.code pre u.cr:before {
4167 content: "\21a4";
4136 content: "\21a4";
4168 display: inline-block;
4137 display: inline-block;
4169 color: rgba(0,0,0,0.5);
4138 color: rgba(0,0,0,0.5);
4170 }
4139 }
4171 table.code-highlighttable div.code-highlight pre u,
4140 table.code-highlighttable div.code-highlight pre u,
4172 table.code-difftable td.code pre u {
4141 table.code-difftable td.code pre u {
4173 color: rgba(0,0,0,0.15);
4142 color: rgba(0,0,0,0.15);
4174 }
4143 }
4175 table.code-highlighttable div.code-highlight pre i,
4144 table.code-highlighttable div.code-highlight pre i,
4176 table.code-difftable td.code pre i {
4145 table.code-difftable td.code pre i {
4177 border-style: solid;
4146 border-style: solid;
4178 border-left-width: 1px;
4147 border-left-width: 1px;
4179 color: rgba(0,0,0,0.5);
4148 color: rgba(0,0,0,0.5);
4180 }
4149 }
4181
4150
4182 /** LINE NUMBERS **/
4151 /** LINE NUMBERS **/
4183 table.code-difftable .lineno {
4152 table.code-difftable .lineno {
4184 padding-left: 2px;
4153 padding-left: 2px;
4185 padding-right: 2px !important;
4154 padding-right: 2px !important;
4186 width: 30px;
4155 width: 30px;
4187 -moz-user-select: none;
4156 -moz-user-select: none;
4188 -webkit-user-select: none;
4157 -webkit-user-select: none;
4189 border-right: 1px solid #CCC !important;
4158 border-right: 1px solid #CCC !important;
4190 border-left: 0px solid #CCC !important;
4159 border-left: 0px solid #CCC !important;
4191 border-top: 0px solid #CCC !important;
4160 border-top: 0px solid #CCC !important;
4192 border-bottom: none !important;
4161 border-bottom: none !important;
4193 vertical-align: middle !important;
4162 vertical-align: middle !important;
4194 text-align: center;
4163 text-align: center;
4195 }
4164 }
4196 table.code-difftable .lineno.new {
4165 table.code-difftable .lineno.new {
4197 text-align: right;
4166 text-align: right;
4198 }
4167 }
4199 table.code-difftable .lineno.old {
4168 table.code-difftable .lineno.old {
4200 text-align: right;
4169 text-align: right;
4201 }
4170 }
4202 table.code-difftable .lineno a {
4171 table.code-difftable .lineno a {
4203 color: #aaa !important;
4172 color: #aaa !important;
4204 font: 11px Lucida Console, Consolas, Monaco, Inconsolata, Liberation Mono, monospace !important;
4173 font: 11px Lucida Console, Consolas, Monaco, Inconsolata, Liberation Mono, monospace !important;
4205 letter-spacing: -1px;
4174 letter-spacing: -1px;
4206 padding-left: 10px;
4175 padding-left: 10px;
4207 padding-right: 8px;
4176 padding-right: 8px;
4208 box-sizing: border-box;
4177 box-sizing: border-box;
4209 cursor: pointer;
4178 cursor: pointer;
4210 display: block;
4179 display: block;
4211 width: 100%;
4180 width: 100%;
4212 }
4181 }
4213
4182
4214 table.code-difftable .line:hover .lineno a {
4183 table.code-difftable .line:hover .lineno a {
4215 color: #333 !important;
4184 color: #333 !important;
4216 }
4185 }
4217
4186
4218 table.code-difftable .lineno-inline {
4187 table.code-difftable .lineno-inline {
4219 background: none repeat scroll 0 0 #FFF !important;
4188 background: none repeat scroll 0 0 #FFF !important;
4220 padding-left: 2px;
4189 padding-left: 2px;
4221 padding-right: 2px;
4190 padding-right: 2px;
4222 text-align: right;
4191 text-align: right;
4223 width: 30px;
4192 width: 30px;
4224 -moz-user-select: none;
4193 -moz-user-select: none;
4225 -webkit-user-select: none;
4194 -webkit-user-select: none;
4226 }
4195 }
4227
4196
4228 /** CODE **/
4197 /** CODE **/
4229 table.code-difftable .code {
4198 table.code-difftable .code {
4230 display: block;
4199 display: block;
4231 width: 100%;
4200 width: 100%;
4232 }
4201 }
4233 table.code-difftable .code td {
4202 table.code-difftable .code td {
4234 margin: 0;
4203 margin: 0;
4235 padding: 0;
4204 padding: 0;
4236 }
4205 }
4237 table.code-difftable .code pre {
4206 table.code-difftable .code pre {
4238 margin: 0 0 0 12px;
4207 margin: 0 0 0 12px;
4239 padding: 0;
4208 padding: 0;
4240 min-height: 17px;
4209 min-height: 17px;
4241 line-height: 17px;
4210 line-height: 17px;
4242 white-space: pre-wrap;
4211 white-space: pre-wrap;
4243 }
4212 }
4244
4213
4245 table.code-difftable .del .code pre:before {
4214 table.code-difftable .del .code pre:before {
4246 content: "-";
4215 content: "-";
4247 color: #800;
4216 color: #800;
4248 float: left;
4217 float: left;
4249 left: -1em;
4218 left: -1em;
4250 position: relative;
4219 position: relative;
4251 width: 0;
4220 width: 0;
4252 }
4221 }
4253
4222
4254 table.code-difftable .add .code pre:before {
4223 table.code-difftable .add .code pre:before {
4255 content: "+";
4224 content: "+";
4256 color: #080;
4225 color: #080;
4257 float: left;
4226 float: left;
4258 left: -1em;
4227 left: -1em;
4259 position: relative;
4228 position: relative;
4260 width: 0;
4229 width: 0;
4261 }
4230 }
4262
4231
4263 table.code-difftable .unmod .code pre:before {
4232 table.code-difftable .unmod .code pre:before {
4264 content: " ";
4233 content: " ";
4265 float: left;
4234 float: left;
4266 left: -1em;
4235 left: -1em;
4267 position: relative;
4236 position: relative;
4268 width: 0;
4237 width: 0;
4269 }
4238 }
4270
4239
4271 .add-bubble {
4240 .add-bubble {
4272 position: relative;
4241 position: relative;
4273 display: none;
4242 display: none;
4274 float: left;
4243 float: left;
4275 width: 0px;
4244 width: 0px;
4276 height: 0px;
4245 height: 0px;
4277 left: -8px;
4246 left: -8px;
4278 box-sizing: border-box;
4247 box-sizing: border-box;
4279 }
4248 }
4280
4249
4281 /* comment bubble, only visible when in a commentable diff */
4250 /* comment bubble, only visible when in a commentable diff */
4282 .commentable-diff tr.line.add:hover td .add-bubble,
4251 .commentable-diff tr.line.add:hover td .add-bubble,
4283 .commentable-diff tr.line.del:hover td .add-bubble,
4252 .commentable-diff tr.line.del:hover td .add-bubble,
4284 .commentable-diff tr.line.unmod:hover td .add-bubble {
4253 .commentable-diff tr.line.unmod:hover td .add-bubble {
4285 display: block;
4254 display: block;
4286 z-index: 1;
4255 z-index: 1;
4287 }
4256 }
4288
4257
4289 .add-bubble div {
4258 .add-bubble div {
4290 background: #577632;
4259 background: #577632;
4291 width: 16px;
4260 width: 16px;
4292 height: 16px;
4261 height: 16px;
4293 cursor: pointer;
4262 cursor: pointer;
4294 padding: 0 2px 2px 0.5px;
4263 padding: 0 2px 2px 0.5px;
4295 border: 1px solid #577632;
4264 border: 1px solid #577632;
4296 border-radius: 3px;
4265 border-radius: 3px;
4297 box-sizing: border-box;
4266 box-sizing: border-box;
4298 }
4267 }
4299
4268
4300 .add-bubble div:before {
4269 .add-bubble div:before {
4301 font-size: 14px;
4270 font-size: 14px;
4302 color: #ffffff;
4271 color: #ffffff;
4303 font-family: "kallithea";
4272 font-family: "kallithea";
4304 content: '\1f5ea';
4273 content: '\1f5ea';
4305 }
4274 }
4306
4275
4307 .add-bubble div:hover {
4276 .add-bubble div:hover {
4308 transform: scale(1.2, 1.2);
4277 transform: scale(1.2, 1.2);
4309 }
4278 }
4310
4279
4311 /* show some context of link targets - but only works when the link target
4280 /* show some context of link targets - but only works when the link target
4312 can be extended with any visual difference */
4281 can be extended with any visual difference */
4313 div.comment:target:before {
4282 div.comment:target:before {
4314 display: block;
4283 display: block;
4315 height: 100px;
4284 height: 100px;
4316 margin: -100px 0 0;
4285 margin: -100px 0 0;
4317 content: "";
4286 content: "";
4318 }
4287 }
4319
4288
4320 div.comment:target>.comment-wrapp {
4289 div.comment:target>.comment-wrapp {
4321 border: solid 2px #ee0 !important;
4290 border: solid 2px #ee0 !important;
4322 margin: 2px 2px 4px 4px;
4291 margin: 2px 2px 4px 4px;
4323 }
4292 }
4324
4293
4325 .lineno:target a {
4294 .lineno:target a {
4326 border: solid 2px #ee0 !important;
4295 border: solid 2px #ee0 !important;
4327 margin: -2px;
4296 margin: -2px;
4328 }
4297 }
4329
4298
4330 .btn-image-diff-show,
4299 .btn-image-diff-show,
4331 .btn-image-diff-swap {
4300 .btn-image-diff-swap {
4332 margin: 5px;
4301 margin: 5px;
4333 }
4302 }
4334
4303
4335 .img-diff {
4304 .img-diff {
4336 max-width: 45%;
4305 max-width: 45%;
4337 height: auto;
4306 height: auto;
4338 margin: 5px;
4307 margin: 5px;
4339 /* http://lea.verou.me/demos/css3-patterns.html */
4308 /* http://lea.verou.me/demos/css3-patterns.html */
4340 background-image:
4309 background-image:
4341 linear-gradient(45deg, #888 25%, transparent 25%, transparent),
4310 linear-gradient(45deg, #888 25%, transparent 25%, transparent),
4342 linear-gradient(-45deg, #888 25%, transparent 25%, transparent),
4311 linear-gradient(-45deg, #888 25%, transparent 25%, transparent),
4343 linear-gradient(45deg, transparent 75%, #888 75%),
4312 linear-gradient(45deg, transparent 75%, #888 75%),
4344 linear-gradient(-45deg, transparent 75%, #888 75%);
4313 linear-gradient(-45deg, transparent 75%, #888 75%);
4345 background-size: 10px 10px;
4314 background-size: 10px 10px;
4346 background-color: #999;
4315 background-color: #999;
4347 }
4316 }
4348
4317
4349 .img-preview {
4318 .img-preview {
4350 max-width: 100%;
4319 max-width: 100%;
4351 height: auto;
4320 height: auto;
4352 margin: 5px;
4321 margin: 5px;
4353 }
4322 }
4354
4323
4355 div.comment-prev-next-links div.prev-comment,
4324 div.comment-prev-next-links div.prev-comment,
4356 div.comment-prev-next-links div.next-comment {
4325 div.comment-prev-next-links div.next-comment {
4357 display: inline-block;
4326 display: inline-block;
4358 min-width: 150px;
4327 min-width: 150px;
4359 margin: 3px 6px;
4328 margin: 3px 6px;
4360 }
4329 }
4361
4330
4362 body table.dataTable thead .sorting {
4331 body table.dataTable thead .sorting {
4363 background-image: none;
4332 background-image: none;
4364 }
4333 }
4365 body table.dataTable thead .sorting_asc {
4334 body table.dataTable thead .sorting_asc {
4366 background-image: none;
4335 background-image: none;
4367 }
4336 }
4368 body table.dataTable thead .sorting_desc {
4337 body table.dataTable thead .sorting_desc {
4369 background-image: none;
4338 background-image: none;
4370 }
4339 }
4371 body table.dataTable thead .sorting_asc_disabled {
4340 body table.dataTable thead .sorting_asc_disabled {
4372 background-image: none;
4341 background-image: none;
4373 }
4342 }
4374 body table.dataTable thead .sorting_desc_disabled {
4343 body table.dataTable thead .sorting_desc_disabled {
4375 background-image: none;
4344 background-image: none;
4376 }
4345 }
4377
4346
4378 body table.dataTable thead .sorting_asc::after {
4347 body table.dataTable thead .sorting_asc::after {
4379 font-family: "kallithea";
4348 font-family: "kallithea";
4380 content: "\23f6";
4349 content: "\23f6";
4381 }
4350 }
4382 body table.dataTable thead .sorting_desc::after {
4351 body table.dataTable thead .sorting_desc::after {
4383 font-family: "kallithea";
4352 font-family: "kallithea";
4384 content: "\23f7";
4353 content: "\23f7";
4385 }
4354 }
4386
4355
4387 .dataTables_wrapper .dataTables_left {
4356 .dataTables_wrapper .dataTables_left {
4388 float: left !important;
4357 float: left !important;
4389 }
4358 }
4390
4359
4391 .dataTables_wrapper .dataTables_right {
4360 .dataTables_wrapper .dataTables_right {
4392 float: right;
4361 float: right;
4393 }
4362 }
4394
4363
4395 .dataTables_wrapper .dataTables_right > div {
4364 .dataTables_wrapper .dataTables_right > div {
4396 padding-left: 30px;
4365 padding-left: 30px;
4397 }
4366 }
4398
4367
4399 .dataTables_wrapper .dataTables_info {
4368 .dataTables_wrapper .dataTables_info {
4400 clear: none;
4369 clear: none;
4401 padding-top: 1em;
4370 padding-top: 1em;
4402 }
4371 }
4403
4372
4404 .dataTables_wrapper .dataTables_paginate {
4373 .dataTables_wrapper .dataTables_paginate {
4405 padding-top: 0;
4374 padding-top: 0;
4406 }
4375 }
4407
4376
4408 .dataTables_wrapper .dataTables_paginate > a.paginate_button {
4377 .dataTables_wrapper .dataTables_paginate > a.paginate_button {
4409 padding-top: 1em;
4378 padding-top: 1em;
4410 border: 0 !important;
4379 border: 0 !important;
4411 }
4380 }
4412
4381
4413 .text-muted {
4382 .text-muted {
4414 color: #777777;
4383 color: #777777;
4415 }
4384 }
4416
4385
4417 .grid_edit a {
4386 .grid_edit a {
4418 text-decoration: none;
4387 text-decoration: none;
4419 }
4388 }
4420
4389
4421 .changes_txt {
4390 .changes_txt {
4422 clear: both;
4391 clear: both;
4423 }
4392 }
4424
4393
4425 .text-nowrap {
4394 .text-nowrap {
4426 white-space: nowrap;
4395 white-space: nowrap;
4427 }
4396 }
4428
4397
4429 div.codeblock div.code-header div.author {
4398 div.codeblock div.code-header div.author {
4430 height: auto;
4399 height: auto;
4431 min-height: 25px;
4400 min-height: 25px;
4432 }
4401 }
4433
4402
4434 ul.user_group_member li {
4403 ul.user_group_member li {
4435 clear: both;
4404 clear: both;
4436 }
4405 }
4406
4407 .tooltip {
4408 position: absolute;
4409 z-index: 1070;
4410 display: block;
4411 font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
4412 font-size: 12px;
4413 font-style: normal;
4414 font-weight: 400;
4415 line-height: 1.42857143;
4416 text-align: left;
4417 text-align: start;
4418 text-decoration: none;
4419 text-shadow: none;
4420 text-transform: none;
4421 letter-spacing: normal;
4422 word-break: normal;
4423 word-spacing: normal;
4424 word-wrap: normal;
4425 white-space: normal;
4426 }
4427 .tooltip-arrow {
4428 position: absolute;
4429 width: 0;
4430 height: 0;
4431 border-color: transparent;
4432 border-style: solid;
4433 }
4434 .tooltip-inner {
4435 max-width: 200px;
4436 padding: 3px 8px;
4437 color: #fff;
4438 text-align: center;
4439 background-color: #000;
4440 border-radius: 4px;
4441 }
4442
4443 .tooltip.top {
4444 padding: 5px 0;
4445 margin-top: -3px;
4446 }
4447 .tooltip.top .tooltip-arrow {
4448 bottom: 0;
4449 left: 50%;
4450 margin-left: -5px;
4451 border-width: 5px 5px 0;
4452 border-top-color: #000;
4453 }
4454
4455 .tooltip.bottom {
4456 padding: 5px 0;
4457 margin-top: 3px;
4458 }
4459 .tooltip.bottom .tooltip-arrow {
4460 top: 0;
4461 left: 50%;
4462 margin-left: -5px;
4463 border-width: 0 5px 5px;
4464 border-bottom-color: #000;
4465 }
4466
4467
4468 .popover {
4469 position: absolute;
4470 top: 0;
4471 left: 0;
4472 z-index: 1060;
4473 max-width: 276px;
4474 padding: 1px;
4475 background-color: #fff;
4476 background-clip: padding-box;
4477 border: 1px solid #ccc;
4478 border: 1px solid rgba(0,0,0,.2);
4479 border-radius: 6px;
4480 box-shadow: 0 5px 10px rgba(0,0,0,.2);
4481 font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
4482 font-size: 12px;
4483 font-style: normal;
4484 font-weight: 400;
4485 line-height: 1.42857143;
4486 text-align: left;
4487 text-align: start;
4488 text-decoration: none;
4489 text-shadow: none;
4490 text-transform: none;
4491 letter-spacing: normal;
4492 word-break: normal;
4493 word-spacing: normal;
4494 word-wrap: normal;
4495 white-space: normal;
4496 }
4497
4498 .popover > .arrow {
4499 border-width: 11px;
4500 }
4501 .popover > .arrow,
4502 .popover > .arrow::after {
4503 position: absolute;
4504 display: block;
4505 width: 0;
4506 height: 0;
4507 border-color: transparent;
4508 border-style: solid;
4509 }
4510
4511 .popover-title {
4512 padding: 8px 14px;
4513 margin: 0;
4514 font-size: 14px;
4515 background-color: #f7f7f7;
4516 border-bottom: 1px solid #ebebeb;
4517 border-radius: 5px 5px 0 0;
4518 }
4519
4520 .popover-content {
4521 padding: 9px 14px;
4522 }
4523
4524 .popover.top {
4525 margin-top: -10px;
4526 }
4527 .popover.top > .arrow {
4528 bottom: -11px;
4529 left: 50%;
4530 margin-left: -11px;
4531 border-top-color: #999;
4532 border-top-color: rgba(0,0,0,.25);
4533 border-bottom-width: 0;
4534 }
4535
4536 .popover.bottom {
4537 margin-top: 10px;
4538 }
4539 .popover.bottom > .arrow {
4540 top: -11px;
4541 left: 50%;
4542 margin-left: -11px;
4543 border-top-width: 0;
4544 border-bottom-color: #999;
4545 border-bottom-color: rgba(0,0,0,.25);
4546 }
@@ -1,1519 +1,1480 b''
1 /**
1 /**
2 Kallithea JS Files
2 Kallithea JS Files
3 **/
3 **/
4 'use strict';
4 'use strict';
5
5
6 if (typeof console == "undefined" || typeof console.log == "undefined"){
6 if (typeof console == "undefined" || typeof console.log == "undefined"){
7 console = { log: function() {} }
7 console = { log: function() {} }
8 }
8 }
9
9
10 /**
10 /**
11 * INJECT .format function into String
11 * INJECT .format function into String
12 * Usage: "My name is {0} {1}".format("Johny","Bravo")
12 * Usage: "My name is {0} {1}".format("Johny","Bravo")
13 * Return "My name is Johny Bravo"
13 * Return "My name is Johny Bravo"
14 * Inspired by https://gist.github.com/1049426
14 * Inspired by https://gist.github.com/1049426
15 */
15 */
16 String.prototype.format = function() {
16 String.prototype.format = function() {
17 function format() {
17 function format() {
18 var str = this;
18 var str = this;
19 var len = arguments.length+1;
19 var len = arguments.length+1;
20 var safe = undefined;
20 var safe = undefined;
21 var arg = undefined;
21 var arg = undefined;
22
22
23 // For each {0} {1} {n...} replace with the argument in that position. If
23 // For each {0} {1} {n...} replace with the argument in that position. If
24 // the argument is an object or an array it will be stringified to JSON.
24 // the argument is an object or an array it will be stringified to JSON.
25 for (var i=0; i < len; arg = arguments[i++]) {
25 for (var i=0; i < len; arg = arguments[i++]) {
26 safe = typeof arg === 'object' ? JSON.stringify(arg) : arg;
26 safe = typeof arg === 'object' ? JSON.stringify(arg) : arg;
27 str = str.replace(RegExp('\\{'+(i-1)+'\\}', 'g'), safe);
27 str = str.replace(RegExp('\\{'+(i-1)+'\\}', 'g'), safe);
28 }
28 }
29 return str;
29 return str;
30 }
30 }
31
31
32 // Save a reference of what may already exist under the property native.
32 // Save a reference of what may already exist under the property native.
33 // Allows for doing something like: if("".format.native) { /* use native */ }
33 // Allows for doing something like: if("".format.native) { /* use native */ }
34 format.native = String.prototype.format;
34 format.native = String.prototype.format;
35
35
36 // Replace the prototype property
36 // Replace the prototype property
37 return format;
37 return format;
38
38
39 }();
39 }();
40
40
41 String.prototype.strip = function(char) {
41 String.prototype.strip = function(char) {
42 if(char === undefined){
42 if(char === undefined){
43 char = '\\s';
43 char = '\\s';
44 }
44 }
45 return this.replace(new RegExp('^'+char+'+|'+char+'+$','g'), '');
45 return this.replace(new RegExp('^'+char+'+|'+char+'+$','g'), '');
46 }
46 }
47
47
48 String.prototype.lstrip = function(char) {
48 String.prototype.lstrip = function(char) {
49 if(char === undefined){
49 if(char === undefined){
50 char = '\\s';
50 char = '\\s';
51 }
51 }
52 return this.replace(new RegExp('^'+char+'+'),'');
52 return this.replace(new RegExp('^'+char+'+'),'');
53 }
53 }
54
54
55 String.prototype.rstrip = function(char) {
55 String.prototype.rstrip = function(char) {
56 if(char === undefined){
56 if(char === undefined){
57 char = '\\s';
57 char = '\\s';
58 }
58 }
59 return this.replace(new RegExp(''+char+'+$'),'');
59 return this.replace(new RegExp(''+char+'+$'),'');
60 }
60 }
61
61
62 /* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf#Polyfill
62 /* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf#Polyfill
63 under MIT license / public domain, see
63 under MIT license / public domain, see
64 https://developer.mozilla.org/en-US/docs/MDN/About#Copyrights_and_licenses */
64 https://developer.mozilla.org/en-US/docs/MDN/About#Copyrights_and_licenses */
65 if(!Array.prototype.indexOf) {
65 if(!Array.prototype.indexOf) {
66 Array.prototype.indexOf = function (searchElement, fromIndex) {
66 Array.prototype.indexOf = function (searchElement, fromIndex) {
67 if ( this === undefined || this === null ) {
67 if ( this === undefined || this === null ) {
68 throw new TypeError( '"this" is null or not defined' );
68 throw new TypeError( '"this" is null or not defined' );
69 }
69 }
70
70
71 var length = this.length >>> 0; // Hack to convert object.length to a UInt32
71 var length = this.length >>> 0; // Hack to convert object.length to a UInt32
72
72
73 fromIndex = +fromIndex || 0;
73 fromIndex = +fromIndex || 0;
74
74
75 if (Math.abs(fromIndex) === Infinity) {
75 if (Math.abs(fromIndex) === Infinity) {
76 fromIndex = 0;
76 fromIndex = 0;
77 }
77 }
78
78
79 if (fromIndex < 0) {
79 if (fromIndex < 0) {
80 fromIndex += length;
80 fromIndex += length;
81 if (fromIndex < 0) {
81 if (fromIndex < 0) {
82 fromIndex = 0;
82 fromIndex = 0;
83 }
83 }
84 }
84 }
85
85
86 for (;fromIndex < length; fromIndex++) {
86 for (;fromIndex < length; fromIndex++) {
87 if (this[fromIndex] === searchElement) {
87 if (this[fromIndex] === searchElement) {
88 return fromIndex;
88 return fromIndex;
89 }
89 }
90 }
90 }
91
91
92 return -1;
92 return -1;
93 };
93 };
94 }
94 }
95
95
96 /* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter#Compatibility
96 /* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter#Compatibility
97 under MIT license / public domain, see
97 under MIT license / public domain, see
98 https://developer.mozilla.org/en-US/docs/MDN/About#Copyrights_and_licenses */
98 https://developer.mozilla.org/en-US/docs/MDN/About#Copyrights_and_licenses */
99 if (!Array.prototype.filter)
99 if (!Array.prototype.filter)
100 {
100 {
101 Array.prototype.filter = function(fun /*, thisArg */)
101 Array.prototype.filter = function(fun /*, thisArg */)
102 {
102 {
103 if (this === void 0 || this === null)
103 if (this === void 0 || this === null)
104 throw new TypeError();
104 throw new TypeError();
105
105
106 var t = Object(this);
106 var t = Object(this);
107 var len = t.length >>> 0;
107 var len = t.length >>> 0;
108 if (typeof fun !== "function")
108 if (typeof fun !== "function")
109 throw new TypeError();
109 throw new TypeError();
110
110
111 var res = [];
111 var res = [];
112 var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
112 var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
113 for (var i = 0; i < len; i++)
113 for (var i = 0; i < len; i++)
114 {
114 {
115 if (i in t)
115 if (i in t)
116 {
116 {
117 var val = t[i];
117 var val = t[i];
118
118
119 // NOTE: Technically this should Object.defineProperty at
119 // NOTE: Technically this should Object.defineProperty at
120 // the next index, as push can be affected by
120 // the next index, as push can be affected by
121 // properties on Object.prototype and Array.prototype.
121 // properties on Object.prototype and Array.prototype.
122 // But that method's new, and collisions should be
122 // But that method's new, and collisions should be
123 // rare, so use the more-compatible alternative.
123 // rare, so use the more-compatible alternative.
124 if (fun.call(thisArg, val, i, t))
124 if (fun.call(thisArg, val, i, t))
125 res.push(val);
125 res.push(val);
126 }
126 }
127 }
127 }
128
128
129 return res;
129 return res;
130 };
130 };
131 }
131 }
132
132
133 /**
133 /**
134 * A customized version of PyRoutes.JS from https://pypi.python.org/pypi/pyroutes.js/
134 * A customized version of PyRoutes.JS from https://pypi.python.org/pypi/pyroutes.js/
135 * which is copyright Stephane Klein and was made available under the BSD License.
135 * which is copyright Stephane Klein and was made available under the BSD License.
136 *
136 *
137 * Usage pyroutes.url('mark_error_fixed',{"error_id":error_id}) // /mark_error_fixed/<error_id>
137 * Usage pyroutes.url('mark_error_fixed',{"error_id":error_id}) // /mark_error_fixed/<error_id>
138 */
138 */
139 var pyroutes = (function() {
139 var pyroutes = (function() {
140 var matchlist = {};
140 var matchlist = {};
141 var sprintf = (function() {
141 var sprintf = (function() {
142 function get_type(variable) {
142 function get_type(variable) {
143 return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
143 return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
144 }
144 }
145 function str_repeat(input, multiplier) {
145 function str_repeat(input, multiplier) {
146 for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}
146 for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}
147 return output.join('');
147 return output.join('');
148 }
148 }
149
149
150 var str_format = function() {
150 var str_format = function() {
151 if (!str_format.cache.hasOwnProperty(arguments[0])) {
151 if (!str_format.cache.hasOwnProperty(arguments[0])) {
152 str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
152 str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
153 }
153 }
154 return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
154 return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
155 };
155 };
156
156
157 str_format.format = function(parse_tree, argv) {
157 str_format.format = function(parse_tree, argv) {
158 var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
158 var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
159 for (i = 0; i < tree_length; i++) {
159 for (i = 0; i < tree_length; i++) {
160 node_type = get_type(parse_tree[i]);
160 node_type = get_type(parse_tree[i]);
161 if (node_type === 'string') {
161 if (node_type === 'string') {
162 output.push(parse_tree[i]);
162 output.push(parse_tree[i]);
163 }
163 }
164 else if (node_type === 'array') {
164 else if (node_type === 'array') {
165 match = parse_tree[i]; // convenience purposes only
165 match = parse_tree[i]; // convenience purposes only
166 if (match[2]) { // keyword argument
166 if (match[2]) { // keyword argument
167 arg = argv[cursor];
167 arg = argv[cursor];
168 for (k = 0; k < match[2].length; k++) {
168 for (k = 0; k < match[2].length; k++) {
169 if (!arg.hasOwnProperty(match[2][k])) {
169 if (!arg.hasOwnProperty(match[2][k])) {
170 throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
170 throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
171 }
171 }
172 arg = arg[match[2][k]];
172 arg = arg[match[2][k]];
173 }
173 }
174 }
174 }
175 else if (match[1]) { // positional argument (explicit)
175 else if (match[1]) { // positional argument (explicit)
176 arg = argv[match[1]];
176 arg = argv[match[1]];
177 }
177 }
178 else { // positional argument (implicit)
178 else { // positional argument (implicit)
179 arg = argv[cursor++];
179 arg = argv[cursor++];
180 }
180 }
181
181
182 if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
182 if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
183 throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
183 throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
184 }
184 }
185 switch (match[8]) {
185 switch (match[8]) {
186 case 'b': arg = arg.toString(2); break;
186 case 'b': arg = arg.toString(2); break;
187 case 'c': arg = String.fromCharCode(arg); break;
187 case 'c': arg = String.fromCharCode(arg); break;
188 case 'd': arg = parseInt(arg, 10); break;
188 case 'd': arg = parseInt(arg, 10); break;
189 case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
189 case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
190 case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
190 case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
191 case 'o': arg = arg.toString(8); break;
191 case 'o': arg = arg.toString(8); break;
192 case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
192 case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
193 case 'u': arg = Math.abs(arg); break;
193 case 'u': arg = Math.abs(arg); break;
194 case 'x': arg = arg.toString(16); break;
194 case 'x': arg = arg.toString(16); break;
195 case 'X': arg = arg.toString(16).toUpperCase(); break;
195 case 'X': arg = arg.toString(16).toUpperCase(); break;
196 }
196 }
197 arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
197 arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
198 pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
198 pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
199 pad_length = match[6] - String(arg).length;
199 pad_length = match[6] - String(arg).length;
200 pad = match[6] ? str_repeat(pad_character, pad_length) : '';
200 pad = match[6] ? str_repeat(pad_character, pad_length) : '';
201 output.push(match[5] ? arg + pad : pad + arg);
201 output.push(match[5] ? arg + pad : pad + arg);
202 }
202 }
203 }
203 }
204 return output.join('');
204 return output.join('');
205 };
205 };
206
206
207 str_format.cache = {};
207 str_format.cache = {};
208
208
209 str_format.parse = function(fmt) {
209 str_format.parse = function(fmt) {
210 var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
210 var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
211 while (_fmt) {
211 while (_fmt) {
212 if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
212 if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
213 parse_tree.push(match[0]);
213 parse_tree.push(match[0]);
214 }
214 }
215 else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
215 else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
216 parse_tree.push('%');
216 parse_tree.push('%');
217 }
217 }
218 else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
218 else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
219 if (match[2]) {
219 if (match[2]) {
220 arg_names |= 1;
220 arg_names |= 1;
221 var field_list = [], replacement_field = match[2], field_match = [];
221 var field_list = [], replacement_field = match[2], field_match = [];
222 if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
222 if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
223 field_list.push(field_match[1]);
223 field_list.push(field_match[1]);
224 while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
224 while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
225 if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
225 if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
226 field_list.push(field_match[1]);
226 field_list.push(field_match[1]);
227 }
227 }
228 else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
228 else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
229 field_list.push(field_match[1]);
229 field_list.push(field_match[1]);
230 }
230 }
231 else {
231 else {
232 throw('[sprintf] huh?');
232 throw('[sprintf] huh?');
233 }
233 }
234 }
234 }
235 }
235 }
236 else {
236 else {
237 throw('[sprintf] huh?');
237 throw('[sprintf] huh?');
238 }
238 }
239 match[2] = field_list;
239 match[2] = field_list;
240 }
240 }
241 else {
241 else {
242 arg_names |= 2;
242 arg_names |= 2;
243 }
243 }
244 if (arg_names === 3) {
244 if (arg_names === 3) {
245 throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
245 throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
246 }
246 }
247 parse_tree.push(match);
247 parse_tree.push(match);
248 }
248 }
249 else {
249 else {
250 throw('[sprintf] huh?');
250 throw('[sprintf] huh?');
251 }
251 }
252 _fmt = _fmt.substring(match[0].length);
252 _fmt = _fmt.substring(match[0].length);
253 }
253 }
254 return parse_tree;
254 return parse_tree;
255 };
255 };
256
256
257 return str_format;
257 return str_format;
258 })();
258 })();
259
259
260 var vsprintf = function(fmt, argv) {
260 var vsprintf = function(fmt, argv) {
261 argv.unshift(fmt);
261 argv.unshift(fmt);
262 return sprintf.apply(null, argv);
262 return sprintf.apply(null, argv);
263 };
263 };
264 return {
264 return {
265 'url': function(route_name, params) {
265 'url': function(route_name, params) {
266 var result = route_name;
266 var result = route_name;
267 if (typeof(params) != 'object'){
267 if (typeof(params) != 'object'){
268 params = {};
268 params = {};
269 }
269 }
270 if (matchlist.hasOwnProperty(route_name)) {
270 if (matchlist.hasOwnProperty(route_name)) {
271 var route = matchlist[route_name];
271 var route = matchlist[route_name];
272 // param substitution
272 // param substitution
273 for(var i=0; i < route[1].length; i++) {
273 for(var i=0; i < route[1].length; i++) {
274 if (!params.hasOwnProperty(route[1][i]))
274 if (!params.hasOwnProperty(route[1][i]))
275 throw new Error(route[1][i] + ' missing in "' + route_name + '" route generation');
275 throw new Error(route[1][i] + ' missing in "' + route_name + '" route generation');
276 }
276 }
277 result = sprintf(route[0], params);
277 result = sprintf(route[0], params);
278
278
279 var ret = [];
279 var ret = [];
280 //extra params => GET
280 //extra params => GET
281 for(var param in params){
281 for(var param in params){
282 if (route[1].indexOf(param) == -1){
282 if (route[1].indexOf(param) == -1){
283 ret.push(encodeURIComponent(param) + "=" + encodeURIComponent(params[param]));
283 ret.push(encodeURIComponent(param) + "=" + encodeURIComponent(params[param]));
284 }
284 }
285 }
285 }
286 var _parts = ret.join("&");
286 var _parts = ret.join("&");
287 if(_parts){
287 if(_parts){
288 result = result +'?'+ _parts
288 result = result +'?'+ _parts
289 }
289 }
290 }
290 }
291
291
292 return result;
292 return result;
293 },
293 },
294 'register': function(route_name, route_tmpl, req_params) {
294 'register': function(route_name, route_tmpl, req_params) {
295 if (typeof(req_params) != 'object') {
295 if (typeof(req_params) != 'object') {
296 req_params = [];
296 req_params = [];
297 }
297 }
298 var keys = [];
298 var keys = [];
299 for (var i=0; i < req_params.length; i++) {
299 for (var i=0; i < req_params.length; i++) {
300 keys.push(req_params[i]);
300 keys.push(req_params[i]);
301 }
301 }
302 matchlist[route_name] = [
302 matchlist[route_name] = [
303 unescape(route_tmpl),
303 unescape(route_tmpl),
304 keys
304 keys
305 ]
305 ]
306 },
306 },
307 '_routes': function(){
307 '_routes': function(){
308 return matchlist;
308 return matchlist;
309 }
309 }
310 }
310 }
311 })();
311 })();
312
312
313
313
314 /* Invoke all functions in callbacks */
314 /* Invoke all functions in callbacks */
315 var _run_callbacks = function(callbacks){
315 var _run_callbacks = function(callbacks){
316 if (callbacks !== undefined){
316 if (callbacks !== undefined){
317 var _l = callbacks.length;
317 var _l = callbacks.length;
318 for (var i=0;i<_l;i++){
318 for (var i=0;i<_l;i++){
319 var func = callbacks[i];
319 var func = callbacks[i];
320 if(typeof(func)=='function'){
320 if(typeof(func)=='function'){
321 try{
321 try{
322 func();
322 func();
323 }catch (err){};
323 }catch (err){};
324 }
324 }
325 }
325 }
326 }
326 }
327 }
327 }
328
328
329 /**
329 /**
330 * turns objects into GET query string
330 * turns objects into GET query string
331 */
331 */
332 var _toQueryString = function(o) {
332 var _toQueryString = function(o) {
333 if(typeof o !== 'object') {
333 if(typeof o !== 'object') {
334 return false;
334 return false;
335 }
335 }
336 var _p, _qs = [];
336 var _p, _qs = [];
337 for(_p in o) {
337 for(_p in o) {
338 _qs.push(encodeURIComponent(_p) + '=' + encodeURIComponent(o[_p]));
338 _qs.push(encodeURIComponent(_p) + '=' + encodeURIComponent(o[_p]));
339 }
339 }
340 return _qs.join('&');
340 return _qs.join('&');
341 };
341 };
342
342
343 /**
343 /**
344 * Load HTML into DOM using Ajax
344 * Load HTML into DOM using Ajax
345 *
345 *
346 * @param $target: load html async and place it (or an error message) here
346 * @param $target: load html async and place it (or an error message) here
347 * @param success: success callback function
347 * @param success: success callback function
348 * @param args: query parameters to pass to url
348 * @param args: query parameters to pass to url
349 */
349 */
350 function asynchtml(url, $target, success, args){
350 function asynchtml(url, $target, success, args){
351 if(args===undefined){
351 if(args===undefined){
352 args=null;
352 args=null;
353 }
353 }
354 $target.html(_TM['Loading ...']).css('opacity','0.3');
354 $target.html(_TM['Loading ...']).css('opacity','0.3');
355
355
356 return $.ajax({url: url, data: args, headers: {'X-PARTIAL-XHR': '1'}, cache: false, dataType: 'html'})
356 return $.ajax({url: url, data: args, headers: {'X-PARTIAL-XHR': '1'}, cache: false, dataType: 'html'})
357 .done(function(html) {
357 .done(function(html) {
358 $target.html(html);
358 $target.html(html);
359 $target.css('opacity','1.0');
359 $target.css('opacity','1.0');
360 //execute the given original callback
360 //execute the given original callback
361 if (success !== undefined && success) {
361 if (success !== undefined && success) {
362 success();
362 success();
363 }
363 }
364 })
364 })
365 .fail(function(jqXHR, textStatus, errorThrown) {
365 .fail(function(jqXHR, textStatus, errorThrown) {
366 if (textStatus == "abort")
366 if (textStatus == "abort")
367 return;
367 return;
368 $target.html('<span class="error_red">ERROR: {0}</span>'.format(textStatus));
368 $target.html('<span class="error_red">ERROR: {0}</span>'.format(textStatus));
369 $target.css('opacity','1.0');
369 $target.css('opacity','1.0');
370 })
370 })
371 ;
371 ;
372 };
372 };
373
373
374 var ajaxGET = function(url, success, failure) {
374 var ajaxGET = function(url, success, failure) {
375 if(failure === undefined) {
375 if(failure === undefined) {
376 failure = function(jqXHR, textStatus, errorThrown) {
376 failure = function(jqXHR, textStatus, errorThrown) {
377 if (textStatus != "abort")
377 if (textStatus != "abort")
378 alert("Ajax GET error: " + textStatus);
378 alert("Ajax GET error: " + textStatus);
379 };
379 };
380 }
380 }
381 return $.ajax({url: url, headers: {'X-PARTIAL-XHR': '1'}, cache: false})
381 return $.ajax({url: url, headers: {'X-PARTIAL-XHR': '1'}, cache: false})
382 .done(success)
382 .done(success)
383 .fail(failure);
383 .fail(failure);
384 };
384 };
385
385
386 var ajaxPOST = function(url, postData, success, failure) {
386 var ajaxPOST = function(url, postData, success, failure) {
387 postData['_authentication_token'] = _authentication_token;
387 postData['_authentication_token'] = _authentication_token;
388 var postData = _toQueryString(postData);
388 var postData = _toQueryString(postData);
389 if(failure === undefined) {
389 if(failure === undefined) {
390 failure = function(jqXHR, textStatus, errorThrown) {
390 failure = function(jqXHR, textStatus, errorThrown) {
391 if (textStatus != "abort")
391 if (textStatus != "abort")
392 alert("Error posting to server: " + textStatus);
392 alert("Error posting to server: " + textStatus);
393 };
393 };
394 }
394 }
395 return $.ajax({url: url, data: postData, type: 'POST', headers: {'X-PARTIAL-XHR': '1'}, cache: false})
395 return $.ajax({url: url, data: postData, type: 'POST', headers: {'X-PARTIAL-XHR': '1'}, cache: false})
396 .done(success)
396 .done(success)
397 .fail(failure);
397 .fail(failure);
398 };
398 };
399
399
400
400
401 /**
401 /**
402 * activate .show_more links
402 * activate .show_more links
403 * the .show_more must have an id that is the the id of an element to hide prefixed with _
403 * the .show_more must have an id that is the the id of an element to hide prefixed with _
404 * the parentnode will be displayed
404 * the parentnode will be displayed
405 */
405 */
406 var show_more_event = function(){
406 var show_more_event = function(){
407 $('.show_more').click(function(e){
407 $('.show_more').click(function(e){
408 var el = e.currentTarget;
408 var el = e.currentTarget;
409 $('#' + el.id.substring(1)).hide();
409 $('#' + el.id.substring(1)).hide();
410 $(el.parentNode).show();
410 $(el.parentNode).show();
411 });
411 });
412 };
412 };
413
413
414 /**
415 * activate .lazy-cs mouseover for showing changeset tooltip
416 */
417 var show_changeset_tooltip = function(){
418 $('.lazy-cs').mouseover(function(e){
419 var $target = $(e.currentTarget);
420 var rid = $target.data('raw_id');
421 var repo_name = $target.data('repo_name');
422 if(rid && !$target.hasClass('tooltip')){
423 _show_tooltip(e, _TM['loading ...']);
424 var url = pyroutes.url('changeset_info', {"repo_name": repo_name, "revision": rid});
425 ajaxGET(url, function(json){
426 $target.addClass('tooltip');
427 _show_tooltip(e, json['message']);
428 _activate_tooltip($target);
429 });
430 }
431 });
432 };
433
414
434 var _onSuccessFollow = function(target){
415 var _onSuccessFollow = function(target){
435 var $target = $(target);
416 var $target = $(target);
436 var $f_cnt = $('#current_followers_count');
417 var $f_cnt = $('#current_followers_count');
437 if ($target.hasClass('follow')) {
418 if ($target.hasClass('follow')) {
438 $target.removeClass('follow').addClass('following');
419 $target.removeClass('follow').addClass('following');
439 $target.prop('title', _TM['Stop following this repository']);
420 $target.prop('title', _TM['Stop following this repository']);
440 if ($f_cnt.html()) {
421 if ($f_cnt.html()) {
441 var cnt = Number($f_cnt.html())+1;
422 var cnt = Number($f_cnt.html())+1;
442 $f_cnt.html(cnt);
423 $f_cnt.html(cnt);
443 }
424 }
444 } else {
425 } else {
445 $target.removeClass('following').addClass('follow');
426 $target.removeClass('following').addClass('follow');
446 $target.prop('title', _TM['Start following this repository']);
427 $target.prop('title', _TM['Start following this repository']);
447 if ($f_cnt.html()) {
428 if ($f_cnt.html()) {
448 var cnt = Number($f_cnt.html())-1;
429 var cnt = Number($f_cnt.html())-1;
449 $f_cnt.html(cnt);
430 $f_cnt.html(cnt);
450 }
431 }
451 }
432 }
452 }
433 }
453
434
454 var toggleFollowingRepo = function(target, follows_repository_id){
435 var toggleFollowingRepo = function(target, follows_repository_id){
455 var args = 'follows_repository_id=' + follows_repository_id;
436 var args = 'follows_repository_id=' + follows_repository_id;
456 args += '&amp;_authentication_token=' + _authentication_token;
437 args += '&amp;_authentication_token=' + _authentication_token;
457 $.post(TOGGLE_FOLLOW_URL, args, function(data){
438 $.post(TOGGLE_FOLLOW_URL, args, function(data){
458 _onSuccessFollow(target);
439 _onSuccessFollow(target);
459 });
440 });
460 return false;
441 return false;
461 };
442 };
462
443
463 var showRepoSize = function(target, repo_name){
444 var showRepoSize = function(target, repo_name){
464 var args = '_authentication_token=' + _authentication_token;
445 var args = '_authentication_token=' + _authentication_token;
465
446
466 if(!$("#" + target).hasClass('loaded')){
447 if(!$("#" + target).hasClass('loaded')){
467 $("#" + target).html(_TM['Loading ...']);
448 $("#" + target).html(_TM['Loading ...']);
468 var url = pyroutes.url('repo_size', {"repo_name":repo_name});
449 var url = pyroutes.url('repo_size', {"repo_name":repo_name});
469 $.post(url, args, function(data) {
450 $.post(url, args, function(data) {
470 $("#" + target).html(data);
451 $("#" + target).html(data);
471 $("#" + target).addClass('loaded');
452 $("#" + target).addClass('loaded');
472 });
453 });
473 }
454 }
474 return false;
455 return false;
475 };
456 };
476
457
477 /**
458 /**
478 * tooltips
459 * load tooltips dynamically based on data attributes, used for .lazy-cs changeset links
479 */
460 */
480
461 var get_changeset_tooltip = function() {
481 var tooltip_activate = function(){
462 var $target = $(this);
482 $(document).ready(_init_tooltip);
463 var tooltip = $target.data('tooltip');
483 };
464 if (!tooltip) {
484
465 var raw_id = $target.data('raw_id');
485 var _activate_tooltip = function($tt){
466 var repo_name = $target.data('repo_name');
486 $tt.mouseover(_show_tooltip);
467 var url = pyroutes.url('changeset_info', {"repo_name": repo_name, "revision": raw_id});
487 $tt.mousemove(_move_tooltip);
488 $tt.mouseout(_close_tooltip);
489 };
490
468
491 var _init_tooltip = function(){
469 $.ajax(url, {
492 var $tipBox = $('#tip-box');
470 async: false,
493 if(!$tipBox.length){
471 success: function(data) {
494 $tipBox = $('<div id="tip-box"></div>');
472 tooltip = data["message"];
495 $(document.body).append($tipBox);
473 }
474 });
475 $target.data('tooltip', tooltip);
496 }
476 }
497
477 return tooltip;
498 $tipBox.hide();
499 $tipBox.css('position', 'absolute');
500 $tipBox.css('max-width', '600px');
501
502 _activate_tooltip($('[data-toggle="tooltip"]'));
503 };
478 };
504
479
505 var _show_tooltip = function(e, tipText, safe){
480 /**
506 e.stopImmediatePropagation();
481 * activate tooltips and popups
507 var el = e.currentTarget;
482 */
508 var $el = $(el);
483 var tooltip_activate = function(){
509 if(tipText){
484 function placement(p, e){
510 // just use it
485 if(e.getBoundingClientRect().top > 2*$(window).height()/3){
511 } else if(el.tagName.toLowerCase() === 'img'){
486 return 'top';
512 tipText = el.alt ? el.alt : '';
487 }else{
513 } else {
488 return 'bottom';
514 tipText = el.title ? el.title : '';
489 }
515 safe = safe || $el.hasClass("safe-html-title");
516 }
490 }
517
491 $(document).ready(function(){
518 if(tipText !== ''){
492 $('[data-toggle="tooltip"]').tooltip({
519 // save org title
493 placement: placement
520 $el.attr('tt_title', tipText);
494 });
521 // reset title to not show org tooltips
495 $('[data-toggle="popover"]').popover({
522 $el.prop('title', '');
496 html: true,
523
497 container: 'body',
524 var $tipBox = $('#tip-box');
498 placement: placement,
525 if (safe) {
499 trigger: 'hover',
526 $tipBox.html(tipText);
500 template: '<div class="popover cs-popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
527 } else {
501 });
528 $tipBox.text(tipText);
502 $('.lazy-cs').tooltip({
529 }
503 title: get_changeset_tooltip,
530 $tipBox.css('display', 'block');
504 placement: placement
531 }
505 });
506 });
532 };
507 };
533
508
534 var _move_tooltip = function(e){
535 e.stopImmediatePropagation();
536 var $tipBox = $('#tip-box');
537 $tipBox.css('top', (e.pageY + 15) + 'px');
538 $tipBox.css('left', (e.pageX + 15) + 'px');
539 };
540
541 var _close_tooltip = function(e){
542 e.stopImmediatePropagation();
543 var $tipBox = $('#tip-box');
544 $tipBox.hide();
545 var el = e.currentTarget;
546 $(el).prop('title', $(el).attr('tt_title'));
547 };
548
509
549 /**
510 /**
550 * Quick filter widget
511 * Quick filter widget
551 *
512 *
552 * @param target: filter input target
513 * @param target: filter input target
553 * @param nodes: list of nodes in html we want to filter.
514 * @param nodes: list of nodes in html we want to filter.
554 * @param display_element function that takes current node from nodes and
515 * @param display_element function that takes current node from nodes and
555 * does hide or show based on the node
516 * does hide or show based on the node
556 */
517 */
557 var q_filter = (function() {
518 var q_filter = (function() {
558 var _namespace = {};
519 var _namespace = {};
559 var namespace = function (target) {
520 var namespace = function (target) {
560 if (!(target in _namespace)) {
521 if (!(target in _namespace)) {
561 _namespace[target] = {};
522 _namespace[target] = {};
562 }
523 }
563 return _namespace[target];
524 return _namespace[target];
564 };
525 };
565 return function (target, $nodes, display_element) {
526 return function (target, $nodes, display_element) {
566 var $nodes = $nodes;
527 var $nodes = $nodes;
567 var $q_filter_field = $('#' + target);
528 var $q_filter_field = $('#' + target);
568 var F = namespace(target);
529 var F = namespace(target);
569
530
570 $q_filter_field.keyup(function (e) {
531 $q_filter_field.keyup(function (e) {
571 clearTimeout(F.filterTimeout);
532 clearTimeout(F.filterTimeout);
572 F.filterTimeout = setTimeout(F.updateFilter, 600);
533 F.filterTimeout = setTimeout(F.updateFilter, 600);
573 });
534 });
574
535
575 F.filterTimeout = null;
536 F.filterTimeout = null;
576
537
577 F.updateFilter = function () {
538 F.updateFilter = function () {
578 // Reset timeout
539 // Reset timeout
579 F.filterTimeout = null;
540 F.filterTimeout = null;
580
541
581 var obsolete = [];
542 var obsolete = [];
582
543
583 var req = $q_filter_field.val().toLowerCase();
544 var req = $q_filter_field.val().toLowerCase();
584
545
585 var showing = 0;
546 var showing = 0;
586 $nodes.each(function () {
547 $nodes.each(function () {
587 var n = this;
548 var n = this;
588 var target_element = display_element(n);
549 var target_element = display_element(n);
589 if (req && n.innerHTML.toLowerCase().indexOf(req) == -1) {
550 if (req && n.innerHTML.toLowerCase().indexOf(req) == -1) {
590 $(target_element).hide();
551 $(target_element).hide();
591 }
552 }
592 else {
553 else {
593 $(target_element).show();
554 $(target_element).show();
594 showing += 1;
555 showing += 1;
595 }
556 }
596 });
557 });
597
558
598 $('#repo_count').html(showing);
559 $('#repo_count').html(showing);
599 /* FIXME: don't hardcode */
560 /* FIXME: don't hardcode */
600 }
561 }
601 }
562 }
602 })();
563 })();
603
564
604
565
605 /**
566 /**
606 * Comment handling
567 * Comment handling
607 */
568 */
608
569
609 // move comments to their right location, inside new trs
570 // move comments to their right location, inside new trs
610 function move_comments($anchorcomments) {
571 function move_comments($anchorcomments) {
611 $anchorcomments.each(function(i, anchorcomment) {
572 $anchorcomments.each(function(i, anchorcomment) {
612 var $anchorcomment = $(anchorcomment);
573 var $anchorcomment = $(anchorcomment);
613 var target_id = $anchorcomment.data('target-id');
574 var target_id = $anchorcomment.data('target-id');
614 var $comment_div = _get_add_comment_div(target_id);
575 var $comment_div = _get_add_comment_div(target_id);
615 var f_path = $anchorcomment.data('f_path');
576 var f_path = $anchorcomment.data('f_path');
616 var line_no = $anchorcomment.data('line_no');
577 var line_no = $anchorcomment.data('line_no');
617 if ($comment_div[0]) {
578 if ($comment_div[0]) {
618 $comment_div.append($anchorcomment.children());
579 $comment_div.append($anchorcomment.children());
619 if (f_path && line_no) {
580 if (f_path && line_no) {
620 _comment_div_append_add($comment_div, f_path, line_no);
581 _comment_div_append_add($comment_div, f_path, line_no);
621 } else {
582 } else {
622 _comment_div_append_form($comment_div, f_path, line_no);
583 _comment_div_append_form($comment_div, f_path, line_no);
623 }
584 }
624 } else {
585 } else {
625 $anchorcomment.before("Comment to {0} line {1} which is outside the diff context:".format(f_path || '?', line_no || '?'));
586 $anchorcomment.before("Comment to {0} line {1} which is outside the diff context:".format(f_path || '?', line_no || '?'));
626 }
587 }
627 });
588 });
628 linkInlineComments($('.firstlink'), $('.comment:first-child'));
589 linkInlineComments($('.firstlink'), $('.comment:first-child'));
629 }
590 }
630
591
631 // comment bubble was clicked - insert new tr and show form
592 // comment bubble was clicked - insert new tr and show form
632 function show_comment_form($bubble) {
593 function show_comment_form($bubble) {
633 var children = $bubble.closest('tr.line').children('[id]');
594 var children = $bubble.closest('tr.line').children('[id]');
634 var line_td_id = children[children.length - 1].id;
595 var line_td_id = children[children.length - 1].id;
635 var $comment_div = _get_add_comment_div(line_td_id);
596 var $comment_div = _get_add_comment_div(line_td_id);
636 var f_path = $bubble.closest('[data-f_path]').data('f_path');
597 var f_path = $bubble.closest('[data-f_path]').data('f_path');
637 var parts = line_td_id.split('_');
598 var parts = line_td_id.split('_');
638 var line_no = parts[parts.length-1];
599 var line_no = parts[parts.length-1];
639 comment_div_state($comment_div, f_path, line_no, true);
600 comment_div_state($comment_div, f_path, line_no, true);
640 }
601 }
641
602
642 // return comment div for target_id - add it if it doesn't exist yet
603 // return comment div for target_id - add it if it doesn't exist yet
643 function _get_add_comment_div(target_id) {
604 function _get_add_comment_div(target_id) {
644 var comments_box_id = 'comments-' + target_id;
605 var comments_box_id = 'comments-' + target_id;
645 var $comments_box = $('#' + comments_box_id);
606 var $comments_box = $('#' + comments_box_id);
646 if (!$comments_box.length) {
607 if (!$comments_box.length) {
647 var html = '<tr><td id="{0}" colspan="3" class="inline-comments"></td></tr>'.format(comments_box_id);
608 var html = '<tr><td id="{0}" colspan="3" class="inline-comments"></td></tr>'.format(comments_box_id);
648 $('#' + target_id).closest('tr').after(html);
609 $('#' + target_id).closest('tr').after(html);
649 $comments_box = $('#' + comments_box_id);
610 $comments_box = $('#' + comments_box_id);
650 }
611 }
651 return $comments_box;
612 return $comments_box;
652 }
613 }
653
614
654 // Set $comment_div state - showing or not showing form and Add button.
615 // Set $comment_div state - showing or not showing form and Add button.
655 // An Add button is shown on non-empty forms when no form is shown.
616 // An Add button is shown on non-empty forms when no form is shown.
656 // The form is controlled by show_form - if undefined, form is only shown for general comments.
617 // The form is controlled by show_form - if undefined, form is only shown for general comments.
657 function comment_div_state($comment_div, f_path, line_no, show_form_opt) {
618 function comment_div_state($comment_div, f_path, line_no, show_form_opt) {
658 var show_form = show_form_opt !== undefined ? show_form_opt : !f_path && !line_no;
619 var show_form = show_form_opt !== undefined ? show_form_opt : !f_path && !line_no;
659 var $forms = $comment_div.children('.comment-inline-form');
620 var $forms = $comment_div.children('.comment-inline-form');
660 var $buttonrow = $comment_div.children('.add-button-row');
621 var $buttonrow = $comment_div.children('.add-button-row');
661 var $comments = $comment_div.children('.comment');
622 var $comments = $comment_div.children('.comment');
662 $forms.remove();
623 $forms.remove();
663 $buttonrow.remove();
624 $buttonrow.remove();
664 if (show_form) {
625 if (show_form) {
665 _comment_div_append_form($comment_div, f_path, line_no);
626 _comment_div_append_form($comment_div, f_path, line_no);
666 } else if ($comments.length) {
627 } else if ($comments.length) {
667 _comment_div_append_add($comment_div, f_path, line_no);
628 _comment_div_append_add($comment_div, f_path, line_no);
668 }
629 }
669 }
630 }
670
631
671 // append an Add button to $comment_div and hook it up to show form
632 // append an Add button to $comment_div and hook it up to show form
672 function _comment_div_append_add($comment_div, f_path, line_no) {
633 function _comment_div_append_add($comment_div, f_path, line_no) {
673 var addlabel = TRANSLATION_MAP['Add Another Comment'];
634 var addlabel = TRANSLATION_MAP['Add Another Comment'];
674 var $add = $('<div class="add-button-row"><span class="btn btn-default btn-xs add-button">{0}</span></div>'.format(addlabel));
635 var $add = $('<div class="add-button-row"><span class="btn btn-default btn-xs add-button">{0}</span></div>'.format(addlabel));
675 $comment_div.append($add);
636 $comment_div.append($add);
676 $add.children('.add-button').click(function(e) {
637 $add.children('.add-button').click(function(e) {
677 comment_div_state($comment_div, f_path, line_no, true);
638 comment_div_state($comment_div, f_path, line_no, true);
678 });
639 });
679 }
640 }
680
641
681 // append a comment form to $comment_div
642 // append a comment form to $comment_div
682 function _comment_div_append_form($comment_div, f_path, line_no) {
643 function _comment_div_append_form($comment_div, f_path, line_no) {
683 var $form_div = $('#comment-inline-form-template').children()
644 var $form_div = $('#comment-inline-form-template').children()
684 .clone()
645 .clone()
685 .addClass('comment-inline-form');
646 .addClass('comment-inline-form');
686 $comment_div.append($form_div);
647 $comment_div.append($form_div);
687 var $form = $comment_div.find("form");
648 var $form = $comment_div.find("form");
688 var $textarea = $form.find('textarea');
649 var $textarea = $form.find('textarea');
689 var $mentions_container = $form.find('div.mentions-container');
650 var $mentions_container = $form.find('div.mentions-container');
690
651
691 $form.submit(function(e) {
652 $form.submit(function(e) {
692 e.preventDefault();
653 e.preventDefault();
693
654
694 var text = $textarea.val();
655 var text = $textarea.val();
695 var review_status = $form.find('input:radio[name=changeset_status]:checked').val();
656 var review_status = $form.find('input:radio[name=changeset_status]:checked').val();
696 var pr_close = $form.find('input:checkbox[name=save_close]:checked').length ? 'on' : '';
657 var pr_close = $form.find('input:checkbox[name=save_close]:checked').length ? 'on' : '';
697 var pr_delete = $form.find('input:checkbox[name=save_delete]:checked').length ? 'delete' : '';
658 var pr_delete = $form.find('input:checkbox[name=save_delete]:checked').length ? 'delete' : '';
698
659
699 if (!text && !review_status && !pr_close && !pr_delete) {
660 if (!text && !review_status && !pr_close && !pr_delete) {
700 alert("Please provide a comment");
661 alert("Please provide a comment");
701 return false;
662 return false;
702 }
663 }
703
664
704 if (pr_delete) {
665 if (pr_delete) {
705 if (text || review_status || pr_close) {
666 if (text || review_status || pr_close) {
706 alert('Cannot delete pull request while making other changes');
667 alert('Cannot delete pull request while making other changes');
707 return false;
668 return false;
708 }
669 }
709 if (!confirm('Confirm to delete this pull request')) {
670 if (!confirm('Confirm to delete this pull request')) {
710 return false;
671 return false;
711 }
672 }
712 var comments = $('.comment').size();
673 var comments = $('.comment').size();
713 if (comments > 0 &&
674 if (comments > 0 &&
714 !confirm('Confirm again to delete this pull request with {0} comments'.format(comments))) {
675 !confirm('Confirm again to delete this pull request with {0} comments'.format(comments))) {
715 return false;
676 return false;
716 }
677 }
717 }
678 }
718
679
719 $form.find('.submitting-overlay').show();
680 $form.find('.submitting-overlay').show();
720
681
721 var postData = {
682 var postData = {
722 'text': text,
683 'text': text,
723 'f_path': f_path,
684 'f_path': f_path,
724 'line': line_no,
685 'line': line_no,
725 'changeset_status': review_status,
686 'changeset_status': review_status,
726 'save_close': pr_close,
687 'save_close': pr_close,
727 'save_delete': pr_delete
688 'save_delete': pr_delete
728 };
689 };
729 var success = function(json_data) {
690 var success = function(json_data) {
730 if (pr_delete) {
691 if (pr_delete) {
731 location = json_data['location'];
692 location = json_data['location'];
732 } else {
693 } else {
733 $comment_div.append(json_data['rendered_text']);
694 $comment_div.append(json_data['rendered_text']);
734 comment_div_state($comment_div, f_path, line_no);
695 comment_div_state($comment_div, f_path, line_no);
735 linkInlineComments($('.firstlink'), $('.comment:first-child'));
696 linkInlineComments($('.firstlink'), $('.comment:first-child'));
736 if ((review_status || pr_close) && !f_path && !line_no) {
697 if ((review_status || pr_close) && !f_path && !line_no) {
737 // Page changed a lot - reload it after closing the submitted form
698 // Page changed a lot - reload it after closing the submitted form
738 comment_div_state($comment_div, f_path, line_no, false);
699 comment_div_state($comment_div, f_path, line_no, false);
739 location.reload(true);
700 location.reload(true);
740 }
701 }
741 }
702 }
742 };
703 };
743 ajaxPOST(AJAX_COMMENT_URL, postData, success);
704 ajaxPOST(AJAX_COMMENT_URL, postData, success);
744 });
705 });
745
706
746 // create event for hide button
707 // create event for hide button
747 $form.find('.hide-inline-form').click(function(e) {
708 $form.find('.hide-inline-form').click(function(e) {
748 comment_div_state($comment_div, f_path, line_no);
709 comment_div_state($comment_div, f_path, line_no);
749 });
710 });
750
711
751 tooltip_activate();
712 tooltip_activate();
752 if ($textarea.length > 0) {
713 if ($textarea.length > 0) {
753 MentionsAutoComplete($textarea, $mentions_container, _USERS_AC_DATA);
714 MentionsAutoComplete($textarea, $mentions_container, _USERS_AC_DATA);
754 }
715 }
755 if (f_path) {
716 if (f_path) {
756 $textarea.focus();
717 $textarea.focus();
757 }
718 }
758 }
719 }
759
720
760
721
761 function deleteComment(comment_id) {
722 function deleteComment(comment_id) {
762 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__', comment_id);
723 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__', comment_id);
763 var postData = {};
724 var postData = {};
764 var success = function(o) {
725 var success = function(o) {
765 $('#comment-'+comment_id).remove();
726 $('#comment-'+comment_id).remove();
766 // Ignore that this might leave a stray Add button (or have a pending form with another comment) ...
727 // Ignore that this might leave a stray Add button (or have a pending form with another comment) ...
767 }
728 }
768 ajaxPOST(url, postData, success);
729 ajaxPOST(url, postData, success);
769 }
730 }
770
731
771
732
772 /**
733 /**
773 * Double link comments
734 * Double link comments
774 */
735 */
775 var linkInlineComments = function($firstlinks, $comments){
736 var linkInlineComments = function($firstlinks, $comments){
776 if ($comments.length > 0) {
737 if ($comments.length > 0) {
777 $firstlinks.html('<a href="#{0}">First comment</a>'.format($comments.prop('id')));
738 $firstlinks.html('<a href="#{0}">First comment</a>'.format($comments.prop('id')));
778 }
739 }
779 if ($comments.length <= 1) {
740 if ($comments.length <= 1) {
780 return;
741 return;
781 }
742 }
782
743
783 $comments.each(function(i, e){
744 $comments.each(function(i, e){
784 var prev = '';
745 var prev = '';
785 if (i > 0){
746 if (i > 0){
786 var prev_anchor = $($comments.get(i-1)).prop('id');
747 var prev_anchor = $($comments.get(i-1)).prop('id');
787 prev = '<a href="#{0}">Previous comment</a>'.format(prev_anchor);
748 prev = '<a href="#{0}">Previous comment</a>'.format(prev_anchor);
788 }
749 }
789 var next = '';
750 var next = '';
790 if (i+1 < $comments.length){
751 if (i+1 < $comments.length){
791 var next_anchor = $($comments.get(i+1)).prop('id');
752 var next_anchor = $($comments.get(i+1)).prop('id');
792 next = '<a href="#{0}">Next comment</a>'.format(next_anchor);
753 next = '<a href="#{0}">Next comment</a>'.format(next_anchor);
793 }
754 }
794 $(this).find('.comment-prev-next-links').html(
755 $(this).find('.comment-prev-next-links').html(
795 '<div class="prev-comment">{0}</div>'.format(prev) +
756 '<div class="prev-comment">{0}</div>'.format(prev) +
796 '<div class="next-comment">{0}</div>'.format(next));
757 '<div class="next-comment">{0}</div>'.format(next));
797 });
758 });
798 }
759 }
799
760
800 /* activate files.html stuff */
761 /* activate files.html stuff */
801 var fileBrowserListeners = function(current_url, node_list_url, url_base){
762 var fileBrowserListeners = function(current_url, node_list_url, url_base){
802 var current_url_branch = "?branch=__BRANCH__";
763 var current_url_branch = "?branch=__BRANCH__";
803
764
804 $('#stay_at_branch').on('click',function(e){
765 $('#stay_at_branch').on('click',function(e){
805 if(e.currentTarget.checked){
766 if(e.currentTarget.checked){
806 var uri = current_url_branch;
767 var uri = current_url_branch;
807 uri = uri.replace('__BRANCH__',e.currentTarget.value);
768 uri = uri.replace('__BRANCH__',e.currentTarget.value);
808 window.location = uri;
769 window.location = uri;
809 }
770 }
810 else{
771 else{
811 window.location = current_url;
772 window.location = current_url;
812 }
773 }
813 });
774 });
814
775
815 var $node_filter = $('#node_filter');
776 var $node_filter = $('#node_filter');
816
777
817 var filterTimeout = null;
778 var filterTimeout = null;
818 var nodes = null;
779 var nodes = null;
819
780
820 var initFilter = function(){
781 var initFilter = function(){
821 $('#node_filter_box_loading').show();
782 $('#node_filter_box_loading').show();
822 $('#search_activate_id').hide();
783 $('#search_activate_id').hide();
823 $('#add_node_id').hide();
784 $('#add_node_id').hide();
824 $.ajax({url: node_list_url, headers: {'X-PARTIAL-XHR': '1'}, cache: false})
785 $.ajax({url: node_list_url, headers: {'X-PARTIAL-XHR': '1'}, cache: false})
825 .done(function(json) {
786 .done(function(json) {
826 nodes = json.nodes;
787 nodes = json.nodes;
827 $('#node_filter_box_loading').hide();
788 $('#node_filter_box_loading').hide();
828 $('#node_filter_box').show();
789 $('#node_filter_box').show();
829 $node_filter.focus();
790 $node_filter.focus();
830 if($node_filter.hasClass('init')){
791 if($node_filter.hasClass('init')){
831 $node_filter.val('');
792 $node_filter.val('');
832 $node_filter.removeClass('init');
793 $node_filter.removeClass('init');
833 }
794 }
834 })
795 })
835 .fail(function() {
796 .fail(function() {
836 console.log('fileBrowserListeners initFilter failed to load');
797 console.log('fileBrowserListeners initFilter failed to load');
837 })
798 })
838 ;
799 ;
839 }
800 }
840
801
841 var updateFilter = function(e) {
802 var updateFilter = function(e) {
842 return function(){
803 return function(){
843 // Reset timeout
804 // Reset timeout
844 filterTimeout = null;
805 filterTimeout = null;
845 var query = e.currentTarget.value.toLowerCase();
806 var query = e.currentTarget.value.toLowerCase();
846 var match = [];
807 var match = [];
847 var matches = 0;
808 var matches = 0;
848 var matches_max = 20;
809 var matches_max = 20;
849 if (query != ""){
810 if (query != ""){
850 for(var i=0;i<nodes.length;i++){
811 for(var i=0;i<nodes.length;i++){
851 var pos = nodes[i].name.toLowerCase().indexOf(query);
812 var pos = nodes[i].name.toLowerCase().indexOf(query);
852 if(query && pos != -1){
813 if(query && pos != -1){
853 matches++
814 matches++
854 //show only certain amount to not kill browser
815 //show only certain amount to not kill browser
855 if (matches > matches_max){
816 if (matches > matches_max){
856 break;
817 break;
857 }
818 }
858
819
859 var n = nodes[i].name;
820 var n = nodes[i].name;
860 var t = nodes[i].type;
821 var t = nodes[i].type;
861 var n_hl = n.substring(0,pos)
822 var n_hl = n.substring(0,pos)
862 + "<b>{0}</b>".format(n.substring(pos,pos+query.length))
823 + "<b>{0}</b>".format(n.substring(pos,pos+query.length))
863 + n.substring(pos+query.length);
824 + n.substring(pos+query.length);
864 var new_url = url_base.replace('__FPATH__',n);
825 var new_url = url_base.replace('__FPATH__',n);
865 match.push('<tr><td><a class="browser-{0}" href="{1}">{2}</a></td><td colspan="5"></td></tr>'.format(t,new_url,n_hl));
826 match.push('<tr><td><a class="browser-{0}" href="{1}">{2}</a></td><td colspan="5"></td></tr>'.format(t,new_url,n_hl));
866 }
827 }
867 if(match.length >= matches_max){
828 if(match.length >= matches_max){
868 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['Search truncated']));
829 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['Search truncated']));
869 break;
830 break;
870 }
831 }
871 }
832 }
872 }
833 }
873 if(query != ""){
834 if(query != ""){
874 $('#tbody').hide();
835 $('#tbody').hide();
875 $('#tbody_filtered').show();
836 $('#tbody_filtered').show();
876
837
877 if (match.length==0){
838 if (match.length==0){
878 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['No matching files']));
839 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['No matching files']));
879 }
840 }
880
841
881 $('#tbody_filtered').html(match.join(""));
842 $('#tbody_filtered').html(match.join(""));
882 }
843 }
883 else{
844 else{
884 $('#tbody').show();
845 $('#tbody').show();
885 $('#tbody_filtered').hide();
846 $('#tbody_filtered').hide();
886 }
847 }
887 }
848 }
888 };
849 };
889
850
890 $('#filter_activate').click(function(){
851 $('#filter_activate').click(function(){
891 initFilter();
852 initFilter();
892 });
853 });
893 $node_filter.click(function(){
854 $node_filter.click(function(){
894 if($node_filter.hasClass('init')){
855 if($node_filter.hasClass('init')){
895 $node_filter.val('');
856 $node_filter.val('');
896 $node_filter.removeClass('init');
857 $node_filter.removeClass('init');
897 }
858 }
898 });
859 });
899 $node_filter.keyup(function(e){
860 $node_filter.keyup(function(e){
900 clearTimeout(filterTimeout);
861 clearTimeout(filterTimeout);
901 filterTimeout = setTimeout(updateFilter(e),600);
862 filterTimeout = setTimeout(updateFilter(e),600);
902 });
863 });
903 };
864 };
904
865
905
866
906 var initCodeMirror = function(textarea_id, baseUrl, resetUrl){
867 var initCodeMirror = function(textarea_id, baseUrl, resetUrl){
907 var myCodeMirror = CodeMirror.fromTextArea($('#' + textarea_id)[0], {
868 var myCodeMirror = CodeMirror.fromTextArea($('#' + textarea_id)[0], {
908 mode: "null",
869 mode: "null",
909 lineNumbers: true,
870 lineNumbers: true,
910 indentUnit: 4,
871 indentUnit: 4,
911 autofocus: true
872 autofocus: true
912 });
873 });
913 CodeMirror.modeURL = baseUrl + "/codemirror/mode/%N/%N.js";
874 CodeMirror.modeURL = baseUrl + "/codemirror/mode/%N/%N.js";
914
875
915 $('#reset').click(function(e){
876 $('#reset').click(function(e){
916 window.location=resetUrl;
877 window.location=resetUrl;
917 });
878 });
918
879
919 $('#file_enable').click(function(){
880 $('#file_enable').click(function(){
920 $('#editor_container').show();
881 $('#editor_container').show();
921 $('#upload_file_container').hide();
882 $('#upload_file_container').hide();
922 $('#filename_container').show();
883 $('#filename_container').show();
923 $('#mimetype_header').show();
884 $('#mimetype_header').show();
924 });
885 });
925
886
926 $('#upload_file_enable').click(function(){
887 $('#upload_file_enable').click(function(){
927 $('#editor_container').hide();
888 $('#editor_container').hide();
928 $('#upload_file_container').show();
889 $('#upload_file_container').show();
929 $('#filename_container').hide();
890 $('#filename_container').hide();
930 $('#mimetype_header').hide();
891 $('#mimetype_header').hide();
931 });
892 });
932
893
933 return myCodeMirror
894 return myCodeMirror
934 };
895 };
935
896
936 var setCodeMirrorMode = function(codeMirrorInstance, mode) {
897 var setCodeMirrorMode = function(codeMirrorInstance, mode) {
937 CodeMirror.autoLoadMode(codeMirrorInstance, mode);
898 CodeMirror.autoLoadMode(codeMirrorInstance, mode);
938 }
899 }
939
900
940
901
941 var _getIdentNode = function(n){
902 var _getIdentNode = function(n){
942 //iterate thrugh nodes until matching interesting node
903 //iterate thrugh nodes until matching interesting node
943
904
944 if (typeof n == 'undefined'){
905 if (typeof n == 'undefined'){
945 return -1
906 return -1
946 }
907 }
947
908
948 if(typeof n.id != "undefined" && n.id.match('L[0-9]+')){
909 if(typeof n.id != "undefined" && n.id.match('L[0-9]+')){
949 return n
910 return n
950 }
911 }
951 else{
912 else{
952 return _getIdentNode(n.parentNode);
913 return _getIdentNode(n.parentNode);
953 }
914 }
954 };
915 };
955
916
956 /* generate links for multi line selects that can be shown by files.html page_highlights.
917 /* generate links for multi line selects that can be shown by files.html page_highlights.
957 * This is a mouseup handler for hlcode from CodeHtmlFormatter and pygmentize */
918 * This is a mouseup handler for hlcode from CodeHtmlFormatter and pygmentize */
958 var getSelectionLink = function(e) {
919 var getSelectionLink = function(e) {
959 //get selection from start/to nodes
920 //get selection from start/to nodes
960 if (typeof window.getSelection != "undefined") {
921 if (typeof window.getSelection != "undefined") {
961 var s = window.getSelection();
922 var s = window.getSelection();
962
923
963 var from = _getIdentNode(s.anchorNode);
924 var from = _getIdentNode(s.anchorNode);
964 var till = _getIdentNode(s.focusNode);
925 var till = _getIdentNode(s.focusNode);
965
926
966 var f_int = parseInt(from.id.replace('L',''));
927 var f_int = parseInt(from.id.replace('L',''));
967 var t_int = parseInt(till.id.replace('L',''));
928 var t_int = parseInt(till.id.replace('L',''));
968
929
969 var yoffset = 35;
930 var yoffset = 35;
970 var ranges = [parseInt(from.id.replace('L','')), parseInt(till.id.replace('L',''))];
931 var ranges = [parseInt(from.id.replace('L','')), parseInt(till.id.replace('L',''))];
971 if (ranges[0] > ranges[1]){
932 if (ranges[0] > ranges[1]){
972 //highlight from bottom
933 //highlight from bottom
973 yoffset = -yoffset;
934 yoffset = -yoffset;
974 ranges = [ranges[1], ranges[0]];
935 ranges = [ranges[1], ranges[0]];
975 }
936 }
976 var $hl_div = $('div#linktt');
937 var $hl_div = $('div#linktt');
977 // if we select more than 2 lines
938 // if we select more than 2 lines
978 if (ranges[0] != ranges[1]){
939 if (ranges[0] != ranges[1]){
979 if ($hl_div.length) {
940 if ($hl_div.length) {
980 $hl_div.html('');
941 $hl_div.html('');
981 } else {
942 } else {
982 $hl_div = $('<div id="linktt" class="hl-tip-box">');
943 $hl_div = $('<div id="linktt" class="hl-tip-box">');
983 $('body').prepend($hl_div);
944 $('body').prepend($hl_div);
984 }
945 }
985
946
986 $hl_div.append($('<a>').html(_TM['Selection Link']).prop('href', location.href.substring(0, location.href.indexOf('#')) + '#L' + ranges[0] + '-'+ranges[1]));
947 $hl_div.append($('<a>').html(_TM['Selection Link']).prop('href', location.href.substring(0, location.href.indexOf('#')) + '#L' + ranges[0] + '-'+ranges[1]));
987 var xy = $(till).offset();
948 var xy = $(till).offset();
988 $hl_div.css('top', (xy.top + yoffset) + 'px').css('left', xy.left + 'px');
949 $hl_div.css('top', (xy.top + yoffset) + 'px').css('left', xy.left + 'px');
989 $hl_div.show();
950 $hl_div.show();
990 }
951 }
991 else{
952 else{
992 $hl_div.hide();
953 $hl_div.hide();
993 }
954 }
994 }
955 }
995 };
956 };
996
957
997 var deleteNotification = function(url, notification_id, callbacks){
958 var deleteNotification = function(url, notification_id, callbacks){
998 var success = function(o){
959 var success = function(o){
999 $("#notification_"+notification_id).remove();
960 $("#notification_"+notification_id).remove();
1000 _run_callbacks(callbacks);
961 _run_callbacks(callbacks);
1001 };
962 };
1002 var failure = function(o){
963 var failure = function(o){
1003 alert("deleteNotification failure");
964 alert("deleteNotification failure");
1004 };
965 };
1005 var postData = {};
966 var postData = {};
1006 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
967 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
1007 ajaxPOST(sUrl, postData, success, failure);
968 ajaxPOST(sUrl, postData, success, failure);
1008 };
969 };
1009
970
1010 var readNotification = function(url, notification_id, callbacks){
971 var readNotification = function(url, notification_id, callbacks){
1011 var success = function(o){
972 var success = function(o){
1012 var $obj = $("#notification_"+notification_id);
973 var $obj = $("#notification_"+notification_id);
1013 $obj.removeClass('unread');
974 $obj.removeClass('unread');
1014 $obj.find('.read-notification').remove();
975 $obj.find('.read-notification').remove();
1015 _run_callbacks(callbacks);
976 _run_callbacks(callbacks);
1016 };
977 };
1017 var failure = function(o){
978 var failure = function(o){
1018 alert("readNotification failure");
979 alert("readNotification failure");
1019 };
980 };
1020 var postData = {};
981 var postData = {};
1021 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
982 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
1022 ajaxPOST(sUrl, postData, success, failure);
983 ajaxPOST(sUrl, postData, success, failure);
1023 };
984 };
1024
985
1025 /**
986 /**
1026 * Autocomplete functionality
987 * Autocomplete functionality
1027 */
988 */
1028
989
1029 // Custom search function for the DataSource of users
990 // Custom search function for the DataSource of users
1030 var autocompleteMatchUsers = function (sQuery, myUsers) {
991 var autocompleteMatchUsers = function (sQuery, myUsers) {
1031 // Case insensitive matching
992 // Case insensitive matching
1032 var query = sQuery.toLowerCase();
993 var query = sQuery.toLowerCase();
1033 var i = 0;
994 var i = 0;
1034 var l = myUsers.length;
995 var l = myUsers.length;
1035 var matches = [];
996 var matches = [];
1036
997
1037 // Match against each name of each contact
998 // Match against each name of each contact
1038 for (; i < l; i++) {
999 for (; i < l; i++) {
1039 var contact = myUsers[i];
1000 var contact = myUsers[i];
1040 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1001 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1041 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1002 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1042 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1003 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1043 matches[matches.length] = contact;
1004 matches[matches.length] = contact;
1044 }
1005 }
1045 }
1006 }
1046 return matches;
1007 return matches;
1047 };
1008 };
1048
1009
1049 // Custom search function for the DataSource of userGroups
1010 // Custom search function for the DataSource of userGroups
1050 var autocompleteMatchGroups = function (sQuery, myGroups) {
1011 var autocompleteMatchGroups = function (sQuery, myGroups) {
1051 // Case insensitive matching
1012 // Case insensitive matching
1052 var query = sQuery.toLowerCase();
1013 var query = sQuery.toLowerCase();
1053 var i = 0;
1014 var i = 0;
1054 var l = myGroups.length;
1015 var l = myGroups.length;
1055 var matches = [];
1016 var matches = [];
1056
1017
1057 // Match against each name of each group
1018 // Match against each name of each group
1058 for (; i < l; i++) {
1019 for (; i < l; i++) {
1059 var matched_group = myGroups[i];
1020 var matched_group = myGroups[i];
1060 if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
1021 if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
1061 matches[matches.length] = matched_group;
1022 matches[matches.length] = matched_group;
1062 }
1023 }
1063 }
1024 }
1064 return matches;
1025 return matches;
1065 };
1026 };
1066
1027
1067 // Helper highlight function for the formatter
1028 // Helper highlight function for the formatter
1068 var autocompleteHighlightMatch = function (full, snippet, matchindex) {
1029 var autocompleteHighlightMatch = function (full, snippet, matchindex) {
1069 return full.substring(0, matchindex)
1030 return full.substring(0, matchindex)
1070 + "<span class='match'>"
1031 + "<span class='match'>"
1071 + full.substr(matchindex, snippet.length)
1032 + full.substr(matchindex, snippet.length)
1072 + "</span>" + full.substring(matchindex + snippet.length);
1033 + "</span>" + full.substring(matchindex + snippet.length);
1073 };
1034 };
1074
1035
1075 // Return html snippet for showing the provided gravatar url
1036 // Return html snippet for showing the provided gravatar url
1076 var gravatar = function(gravatar_lnk, size, cssclass) {
1037 var gravatar = function(gravatar_lnk, size, cssclass) {
1077 if (!gravatar_lnk) {
1038 if (!gravatar_lnk) {
1078 return '';
1039 return '';
1079 }
1040 }
1080 if (gravatar_lnk == 'default') {
1041 if (gravatar_lnk == 'default') {
1081 return '<i class="icon-user {1}" style="font-size: {0}px;"></i>'.format(size, cssclass);
1042 return '<i class="icon-user {1}" style="font-size: {0}px;"></i>'.format(size, cssclass);
1082 }
1043 }
1083 return '<img alt="" class="{2}" style="width: {0}px; height: {0}px" src="{1}"/>'.format(size, gravatar_lnk, cssclass);
1044 return '<img alt="" class="{2}" style="width: {0}px; height: {0}px" src="{1}"/>'.format(size, gravatar_lnk, cssclass);
1084 }
1045 }
1085
1046
1086 var autocompleteGravatar = function(res, gravatar_lnk, size, group) {
1047 var autocompleteGravatar = function(res, gravatar_lnk, size, group) {
1087 var elem;
1048 var elem;
1088 if (group !== undefined) {
1049 if (group !== undefined) {
1089 elem = '<i class="perm-gravatar-ac icon-users"></i>';
1050 elem = '<i class="perm-gravatar-ac icon-users"></i>';
1090 } else {
1051 } else {
1091 elem = gravatar(gravatar_lnk, size, "perm-gravatar-ac");
1052 elem = gravatar(gravatar_lnk, size, "perm-gravatar-ac");
1092 }
1053 }
1093 return '<div class="ac-container-wrap">{0}{1}</div>'.format(elem, res);
1054 return '<div class="ac-container-wrap">{0}{1}</div>'.format(elem, res);
1094 }
1055 }
1095
1056
1096 // Custom formatter to highlight the matching letters
1057 // Custom formatter to highlight the matching letters
1097 var autocompleteFormatter = function (oResultData, sQuery, sResultMatch) {
1058 var autocompleteFormatter = function (oResultData, sQuery, sResultMatch) {
1098 var query = sQuery.toLowerCase();
1059 var query = sQuery.toLowerCase();
1099
1060
1100 // group
1061 // group
1101 if (oResultData.grname != undefined) {
1062 if (oResultData.grname != undefined) {
1102 var grname = oResultData.grname;
1063 var grname = oResultData.grname;
1103 var grmembers = oResultData.grmembers;
1064 var grmembers = oResultData.grmembers;
1104 var grnameMatchIndex = grname.toLowerCase().indexOf(query);
1065 var grnameMatchIndex = grname.toLowerCase().indexOf(query);
1105 var grprefix = "{0}: ".format(_TM['Group']);
1066 var grprefix = "{0}: ".format(_TM['Group']);
1106 var grsuffix = " ({0} {1})".format(grmembers, _TM['members']);
1067 var grsuffix = " ({0} {1})".format(grmembers, _TM['members']);
1107
1068
1108 if (grnameMatchIndex > -1) {
1069 if (grnameMatchIndex > -1) {
1109 return autocompleteGravatar(grprefix + autocompleteHighlightMatch(grname, query, grnameMatchIndex) + grsuffix, null, null, true);
1070 return autocompleteGravatar(grprefix + autocompleteHighlightMatch(grname, query, grnameMatchIndex) + grsuffix, null, null, true);
1110 }
1071 }
1111 return autocompleteGravatar(grprefix + oResultData.grname + grsuffix, null, null, true);
1072 return autocompleteGravatar(grprefix + oResultData.grname + grsuffix, null, null, true);
1112
1073
1113 // users
1074 // users
1114 } else if (oResultData.nname != undefined) {
1075 } else if (oResultData.nname != undefined) {
1115 var fname = oResultData.fname || "";
1076 var fname = oResultData.fname || "";
1116 var lname = oResultData.lname || "";
1077 var lname = oResultData.lname || "";
1117 var nname = oResultData.nname;
1078 var nname = oResultData.nname;
1118
1079
1119 // Guard against null value
1080 // Guard against null value
1120 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1081 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1121 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1082 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1122 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1083 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1123 displayfname, displaylname, displaynname, displayname;
1084 displayfname, displaylname, displaynname, displayname;
1124
1085
1125 if (fnameMatchIndex > -1) {
1086 if (fnameMatchIndex > -1) {
1126 displayfname = autocompleteHighlightMatch(fname, query, fnameMatchIndex);
1087 displayfname = autocompleteHighlightMatch(fname, query, fnameMatchIndex);
1127 } else {
1088 } else {
1128 displayfname = fname;
1089 displayfname = fname;
1129 }
1090 }
1130
1091
1131 if (lnameMatchIndex > -1) {
1092 if (lnameMatchIndex > -1) {
1132 displaylname = autocompleteHighlightMatch(lname, query, lnameMatchIndex);
1093 displaylname = autocompleteHighlightMatch(lname, query, lnameMatchIndex);
1133 } else {
1094 } else {
1134 displaylname = lname;
1095 displaylname = lname;
1135 }
1096 }
1136
1097
1137 if (nnameMatchIndex > -1) {
1098 if (nnameMatchIndex > -1) {
1138 displaynname = autocompleteHighlightMatch(nname, query, nnameMatchIndex);
1099 displaynname = autocompleteHighlightMatch(nname, query, nnameMatchIndex);
1139 } else {
1100 } else {
1140 displaynname = nname;
1101 displaynname = nname;
1141 }
1102 }
1142
1103
1143 displayname = displaynname;
1104 displayname = displaynname;
1144 if (displayfname && displaylname) {
1105 if (displayfname && displaylname) {
1145 displayname = "{0} {1} ({2})".format(displayfname, displaylname, displayname);
1106 displayname = "{0} {1} ({2})".format(displayfname, displaylname, displayname);
1146 }
1107 }
1147
1108
1148 return autocompleteGravatar(displayname, oResultData.gravatar_lnk, oResultData.gravatar_size);
1109 return autocompleteGravatar(displayname, oResultData.gravatar_lnk, oResultData.gravatar_size);
1149 } else {
1110 } else {
1150 return '';
1111 return '';
1151 }
1112 }
1152 };
1113 };
1153
1114
1154 // Generate a basic autocomplete instance that can be tweaked further by the caller
1115 // Generate a basic autocomplete instance that can be tweaked further by the caller
1155 var autocompleteCreate = function ($inputElement, $container, matchFunc) {
1116 var autocompleteCreate = function ($inputElement, $container, matchFunc) {
1156 var datasource = new YAHOO.util.FunctionDataSource(matchFunc);
1117 var datasource = new YAHOO.util.FunctionDataSource(matchFunc);
1157
1118
1158 var autocomplete = new YAHOO.widget.AutoComplete($inputElement[0], $container[0], datasource);
1119 var autocomplete = new YAHOO.widget.AutoComplete($inputElement[0], $container[0], datasource);
1159 autocomplete.useShadow = false;
1120 autocomplete.useShadow = false;
1160 autocomplete.resultTypeList = false;
1121 autocomplete.resultTypeList = false;
1161 autocomplete.animVert = false;
1122 autocomplete.animVert = false;
1162 autocomplete.animHoriz = false;
1123 autocomplete.animHoriz = false;
1163 autocomplete.animSpeed = 0.1;
1124 autocomplete.animSpeed = 0.1;
1164 autocomplete.formatResult = autocompleteFormatter;
1125 autocomplete.formatResult = autocompleteFormatter;
1165
1126
1166 return autocomplete;
1127 return autocomplete;
1167 }
1128 }
1168
1129
1169 var SimpleUserAutoComplete = function ($inputElement, $container, users_list) {
1130 var SimpleUserAutoComplete = function ($inputElement, $container, users_list) {
1170
1131
1171 var matchUsers = function (sQuery) {
1132 var matchUsers = function (sQuery) {
1172 return autocompleteMatchUsers(sQuery, users_list);
1133 return autocompleteMatchUsers(sQuery, users_list);
1173 }
1134 }
1174
1135
1175 var userAC = autocompleteCreate($inputElement, $container, matchUsers);
1136 var userAC = autocompleteCreate($inputElement, $container, matchUsers);
1176
1137
1177 // Handler for selection of an entry
1138 // Handler for selection of an entry
1178 var itemSelectHandler = function (sType, aArgs) {
1139 var itemSelectHandler = function (sType, aArgs) {
1179 var myAC = aArgs[0]; // reference back to the AC instance
1140 var myAC = aArgs[0]; // reference back to the AC instance
1180 var elLI = aArgs[1]; // reference to the selected LI element
1141 var elLI = aArgs[1]; // reference to the selected LI element
1181 var oData = aArgs[2]; // object literal of selected item's result data
1142 var oData = aArgs[2]; // object literal of selected item's result data
1182 myAC.getInputEl().value = oData.nname;
1143 myAC.getInputEl().value = oData.nname;
1183 };
1144 };
1184 userAC.itemSelectEvent.subscribe(itemSelectHandler);
1145 userAC.itemSelectEvent.subscribe(itemSelectHandler);
1185 }
1146 }
1186
1147
1187 var MembersAutoComplete = function ($inputElement, $container, users_list, groups_list) {
1148 var MembersAutoComplete = function ($inputElement, $container, users_list, groups_list) {
1188
1149
1189 var matchAll = function (sQuery) {
1150 var matchAll = function (sQuery) {
1190 var u = autocompleteMatchUsers(sQuery, users_list);
1151 var u = autocompleteMatchUsers(sQuery, users_list);
1191 var g = autocompleteMatchGroups(sQuery, groups_list);
1152 var g = autocompleteMatchGroups(sQuery, groups_list);
1192 return u.concat(g);
1153 return u.concat(g);
1193 };
1154 };
1194
1155
1195 var membersAC = autocompleteCreate($inputElement, $container, matchAll);
1156 var membersAC = autocompleteCreate($inputElement, $container, matchAll);
1196
1157
1197 // Handler for selection of an entry
1158 // Handler for selection of an entry
1198 var itemSelectHandler = function (sType, aArgs) {
1159 var itemSelectHandler = function (sType, aArgs) {
1199 var nextId = $inputElement.prop('id').split('perm_new_member_name_')[1];
1160 var nextId = $inputElement.prop('id').split('perm_new_member_name_')[1];
1200 var myAC = aArgs[0]; // reference back to the AC instance
1161 var myAC = aArgs[0]; // reference back to the AC instance
1201 var elLI = aArgs[1]; // reference to the selected LI element
1162 var elLI = aArgs[1]; // reference to the selected LI element
1202 var oData = aArgs[2]; // object literal of selected item's result data
1163 var oData = aArgs[2]; // object literal of selected item's result data
1203 //fill the autocomplete with value
1164 //fill the autocomplete with value
1204 if (oData.nname != undefined) {
1165 if (oData.nname != undefined) {
1205 //users
1166 //users
1206 myAC.getInputEl().value = oData.nname;
1167 myAC.getInputEl().value = oData.nname;
1207 $('#perm_new_member_type_'+nextId).val('user');
1168 $('#perm_new_member_type_'+nextId).val('user');
1208 } else {
1169 } else {
1209 //groups
1170 //groups
1210 myAC.getInputEl().value = oData.grname;
1171 myAC.getInputEl().value = oData.grname;
1211 $('#perm_new_member_type_'+nextId).val('users_group');
1172 $('#perm_new_member_type_'+nextId).val('users_group');
1212 }
1173 }
1213 };
1174 };
1214 membersAC.itemSelectEvent.subscribe(itemSelectHandler);
1175 membersAC.itemSelectEvent.subscribe(itemSelectHandler);
1215 }
1176 }
1216
1177
1217 var MentionsAutoComplete = function ($inputElement, $container, users_list) {
1178 var MentionsAutoComplete = function ($inputElement, $container, users_list) {
1218
1179
1219 var matchUsers = function (sQuery) {
1180 var matchUsers = function (sQuery) {
1220 var org_sQuery = sQuery;
1181 var org_sQuery = sQuery;
1221 if(this.mentionQuery == null){
1182 if(this.mentionQuery == null){
1222 return []
1183 return []
1223 }
1184 }
1224 sQuery = this.mentionQuery;
1185 sQuery = this.mentionQuery;
1225 return autocompleteMatchUsers(sQuery, users_list);
1186 return autocompleteMatchUsers(sQuery, users_list);
1226 }
1187 }
1227
1188
1228 var mentionsAC = autocompleteCreate($inputElement, $container, matchUsers);
1189 var mentionsAC = autocompleteCreate($inputElement, $container, matchUsers);
1229 mentionsAC.suppressInputUpdate = true;
1190 mentionsAC.suppressInputUpdate = true;
1230 // Overwrite formatResult to take into account mentionQuery
1191 // Overwrite formatResult to take into account mentionQuery
1231 mentionsAC.formatResult = function (oResultData, sQuery, sResultMatch) {
1192 mentionsAC.formatResult = function (oResultData, sQuery, sResultMatch) {
1232 var org_sQuery = sQuery;
1193 var org_sQuery = sQuery;
1233 if (this.dataSource.mentionQuery != null) {
1194 if (this.dataSource.mentionQuery != null) {
1234 sQuery = this.dataSource.mentionQuery;
1195 sQuery = this.dataSource.mentionQuery;
1235 }
1196 }
1236 return autocompleteFormatter(oResultData, sQuery, sResultMatch);
1197 return autocompleteFormatter(oResultData, sQuery, sResultMatch);
1237 }
1198 }
1238
1199
1239 // Handler for selection of an entry
1200 // Handler for selection of an entry
1240 if(mentionsAC.itemSelectEvent){
1201 if(mentionsAC.itemSelectEvent){
1241 mentionsAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1202 mentionsAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1242 var myAC = aArgs[0]; // reference back to the AC instance
1203 var myAC = aArgs[0]; // reference back to the AC instance
1243 var elLI = aArgs[1]; // reference to the selected LI element
1204 var elLI = aArgs[1]; // reference to the selected LI element
1244 var oData = aArgs[2]; // object literal of selected item's result data
1205 var oData = aArgs[2]; // object literal of selected item's result data
1245 //Replace the mention name with replaced
1206 //Replace the mention name with replaced
1246 var re = new RegExp();
1207 var re = new RegExp();
1247 var org = myAC.getInputEl().value;
1208 var org = myAC.getInputEl().value;
1248 var chunks = myAC.dataSource.chunks
1209 var chunks = myAC.dataSource.chunks
1249 // replace middle chunk(the search term) with actuall match
1210 // replace middle chunk(the search term) with actuall match
1250 chunks[1] = chunks[1].replace('@'+myAC.dataSource.mentionQuery,
1211 chunks[1] = chunks[1].replace('@'+myAC.dataSource.mentionQuery,
1251 '@'+oData.nname+' ');
1212 '@'+oData.nname+' ');
1252 myAC.getInputEl().value = chunks.join('');
1213 myAC.getInputEl().value = chunks.join('');
1253 myAC.getInputEl().focus(); // Y U NO WORK !?
1214 myAC.getInputEl().focus(); // Y U NO WORK !?
1254 });
1215 });
1255 }
1216 }
1256
1217
1257 // in this keybuffer we will gather current value of search !
1218 // in this keybuffer we will gather current value of search !
1258 // since we need to get this just when someone does `@` then we do the
1219 // since we need to get this just when someone does `@` then we do the
1259 // search
1220 // search
1260 mentionsAC.dataSource.chunks = [];
1221 mentionsAC.dataSource.chunks = [];
1261 mentionsAC.dataSource.mentionQuery = null;
1222 mentionsAC.dataSource.mentionQuery = null;
1262
1223
1263 mentionsAC.get_mention = function(msg, max_pos) {
1224 mentionsAC.get_mention = function(msg, max_pos) {
1264 var org = msg;
1225 var org = msg;
1265 // Must match utils2.py MENTIONS_REGEX.
1226 // Must match utils2.py MENTIONS_REGEX.
1266 // Only matching on string up to cursor, so it must end with $
1227 // Only matching on string up to cursor, so it must end with $
1267 var re = new RegExp('(?:^|[^a-zA-Z0-9])@([a-zA-Z0-9][-_.a-zA-Z0-9]*[a-zA-Z0-9])$');
1228 var re = new RegExp('(?:^|[^a-zA-Z0-9])@([a-zA-Z0-9][-_.a-zA-Z0-9]*[a-zA-Z0-9])$');
1268 var chunks = [];
1229 var chunks = [];
1269
1230
1270 // cut first chunk until current pos
1231 // cut first chunk until current pos
1271 var to_max = msg.substr(0, max_pos);
1232 var to_max = msg.substr(0, max_pos);
1272 var at_pos = Math.max(0,to_max.lastIndexOf('@')-1);
1233 var at_pos = Math.max(0,to_max.lastIndexOf('@')-1);
1273 var msg2 = to_max.substr(at_pos);
1234 var msg2 = to_max.substr(at_pos);
1274
1235
1275 chunks.push(org.substr(0,at_pos)); // prefix chunk
1236 chunks.push(org.substr(0,at_pos)); // prefix chunk
1276 chunks.push(msg2); // search chunk
1237 chunks.push(msg2); // search chunk
1277 chunks.push(org.substr(max_pos)); // postfix chunk
1238 chunks.push(org.substr(max_pos)); // postfix chunk
1278
1239
1279 // clean up msg2 for filtering and regex match
1240 // clean up msg2 for filtering and regex match
1280 var msg2 = msg2.lstrip(' ').lstrip('\n');
1241 var msg2 = msg2.lstrip(' ').lstrip('\n');
1281
1242
1282 if(re.test(msg2)){
1243 if(re.test(msg2)){
1283 var unam = re.exec(msg2)[1];
1244 var unam = re.exec(msg2)[1];
1284 return [unam, chunks];
1245 return [unam, chunks];
1285 }
1246 }
1286 return [null, null];
1247 return [null, null];
1287 };
1248 };
1288
1249
1289 $inputElement.keyup(function(e){
1250 $inputElement.keyup(function(e){
1290 var currentMessage = $inputElement.val();
1251 var currentMessage = $inputElement.val();
1291 var currentCaretPosition = $inputElement[0].selectionStart;
1252 var currentCaretPosition = $inputElement[0].selectionStart;
1292
1253
1293 var unam = mentionsAC.get_mention(currentMessage, currentCaretPosition);
1254 var unam = mentionsAC.get_mention(currentMessage, currentCaretPosition);
1294 var curr_search = null;
1255 var curr_search = null;
1295 if(unam[0]){
1256 if(unam[0]){
1296 curr_search = unam[0];
1257 curr_search = unam[0];
1297 }
1258 }
1298
1259
1299 mentionsAC.dataSource.chunks = unam[1];
1260 mentionsAC.dataSource.chunks = unam[1];
1300 mentionsAC.dataSource.mentionQuery = curr_search;
1261 mentionsAC.dataSource.mentionQuery = curr_search;
1301 });
1262 });
1302 }
1263 }
1303
1264
1304 var addReviewMember = function(id,fname,lname,nname,gravatar_link,gravatar_size){
1265 var addReviewMember = function(id,fname,lname,nname,gravatar_link,gravatar_size){
1305 var displayname = nname;
1266 var displayname = nname;
1306 if ((fname != "") && (lname != "")) {
1267 if ((fname != "") && (lname != "")) {
1307 displayname = "{0} {1} ({2})".format(fname, lname, nname);
1268 displayname = "{0} {1} ({2})".format(fname, lname, nname);
1308 }
1269 }
1309 var gravatarelm = gravatar(gravatar_link, gravatar_size, "");
1270 var gravatarelm = gravatar(gravatar_link, gravatar_size, "");
1310 // WARNING: the HTML below is duplicate with
1271 // WARNING: the HTML below is duplicate with
1311 // kallithea/templates/pullrequests/pullrequest_show.html
1272 // kallithea/templates/pullrequests/pullrequest_show.html
1312 // If you change something here it should be reflected in the template too.
1273 // If you change something here it should be reflected in the template too.
1313 var element = (
1274 var element = (
1314 ' <li id="reviewer_{2}">\n'+
1275 ' <li id="reviewer_{2}">\n'+
1315 ' <span class="reviewers_member">\n'+
1276 ' <span class="reviewers_member">\n'+
1316 ' <span class="reviewer_status" data-toggle="tooltip" title="not_reviewed">\n'+
1277 ' <span class="reviewer_status" data-toggle="tooltip" title="not_reviewed">\n'+
1317 ' <i class="icon-circle changeset-status-not_reviewed"></i>\n'+
1278 ' <i class="icon-circle changeset-status-not_reviewed"></i>\n'+
1318 ' </span>\n'+
1279 ' </span>\n'+
1319 (gravatarelm ?
1280 (gravatarelm ?
1320 ' {0}\n' :
1281 ' {0}\n' :
1321 '')+
1282 '')+
1322 ' <span>{1}</span>\n'+
1283 ' <span>{1}</span>\n'+
1323 ' <input type="hidden" value="{2}" name="review_members" />\n'+
1284 ' <input type="hidden" value="{2}" name="review_members" />\n'+
1324 ' <a href="#" class="reviewer_member_remove" onclick="removeReviewMember({2})">\n'+
1285 ' <a href="#" class="reviewer_member_remove" onclick="removeReviewMember({2})">\n'+
1325 ' <i class="icon-minus-circled"></i>\n'+
1286 ' <i class="icon-minus-circled"></i>\n'+
1326 ' </a> (add not saved)\n'+
1287 ' </a> (add not saved)\n'+
1327 ' </span>\n'+
1288 ' </span>\n'+
1328 ' </li>\n'
1289 ' </li>\n'
1329 ).format(gravatarelm, displayname, id);
1290 ).format(gravatarelm, displayname, id);
1330 // check if we don't have this ID already in
1291 // check if we don't have this ID already in
1331 var ids = [];
1292 var ids = [];
1332 $('#review_members').find('li').each(function() {
1293 $('#review_members').find('li').each(function() {
1333 ids.push(this.id);
1294 ids.push(this.id);
1334 });
1295 });
1335 if(ids.indexOf('reviewer_'+id) == -1){
1296 if(ids.indexOf('reviewer_'+id) == -1){
1336 //only add if it's not there
1297 //only add if it's not there
1337 $('#review_members').append(element);
1298 $('#review_members').append(element);
1338 }
1299 }
1339 }
1300 }
1340
1301
1341 var removeReviewMember = function(reviewer_id, repo_name, pull_request_id){
1302 var removeReviewMember = function(reviewer_id, repo_name, pull_request_id){
1342 var $li = $('#reviewer_{0}'.format(reviewer_id));
1303 var $li = $('#reviewer_{0}'.format(reviewer_id));
1343 $li.find('div div').css("text-decoration", "line-through");
1304 $li.find('div div').css("text-decoration", "line-through");
1344 $li.find('input').prop('name', 'review_members_removed');
1305 $li.find('input').prop('name', 'review_members_removed');
1345 $li.find('.reviewer_member_remove').replaceWith('&nbsp;(remove not saved)');
1306 $li.find('.reviewer_member_remove').replaceWith('&nbsp;(remove not saved)');
1346 }
1307 }
1347
1308
1348 /* activate auto completion of users as PR reviewers */
1309 /* activate auto completion of users as PR reviewers */
1349 var PullRequestAutoComplete = function ($inputElement, $container, users_list) {
1310 var PullRequestAutoComplete = function ($inputElement, $container, users_list) {
1350
1311
1351 var matchUsers = function (sQuery) {
1312 var matchUsers = function (sQuery) {
1352 return autocompleteMatchUsers(sQuery, users_list);
1313 return autocompleteMatchUsers(sQuery, users_list);
1353 };
1314 };
1354
1315
1355 var reviewerAC = autocompleteCreate($inputElement, $container, matchUsers);
1316 var reviewerAC = autocompleteCreate($inputElement, $container, matchUsers);
1356 reviewerAC.suppressInputUpdate = true;
1317 reviewerAC.suppressInputUpdate = true;
1357
1318
1358 // Handler for selection of an entry
1319 // Handler for selection of an entry
1359 if(reviewerAC.itemSelectEvent){
1320 if(reviewerAC.itemSelectEvent){
1360 reviewerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1321 reviewerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1361 var myAC = aArgs[0]; // reference back to the AC instance
1322 var myAC = aArgs[0]; // reference back to the AC instance
1362 var elLI = aArgs[1]; // reference to the selected LI element
1323 var elLI = aArgs[1]; // reference to the selected LI element
1363 var oData = aArgs[2]; // object literal of selected item's result data
1324 var oData = aArgs[2]; // object literal of selected item's result data
1364
1325
1365 addReviewMember(oData.id, oData.fname, oData.lname, oData.nname,
1326 addReviewMember(oData.id, oData.fname, oData.lname, oData.nname,
1366 oData.gravatar_lnk, oData.gravatar_size);
1327 oData.gravatar_lnk, oData.gravatar_size);
1367 myAC.getInputEl().value = '';
1328 myAC.getInputEl().value = '';
1368 });
1329 });
1369 }
1330 }
1370 }
1331 }
1371
1332
1372
1333
1373 var addPermAction = function(_html, users_list, groups_list){
1334 var addPermAction = function(_html, users_list, groups_list){
1374 var $last_node = $('.last_new_member').last(); // empty tr between last and add
1335 var $last_node = $('.last_new_member').last(); // empty tr between last and add
1375 var next_id = $('.new_members').length;
1336 var next_id = $('.new_members').length;
1376 $last_node.before($('<tr class="new_members">').append(_html.format(next_id)));
1337 $last_node.before($('<tr class="new_members">').append(_html.format(next_id)));
1377 MembersAutoComplete($("#perm_new_member_name_"+next_id),
1338 MembersAutoComplete($("#perm_new_member_name_"+next_id),
1378 $("#perm_container_"+next_id), users_list, groups_list);
1339 $("#perm_container_"+next_id), users_list, groups_list);
1379 }
1340 }
1380
1341
1381 function ajaxActionRevokePermission(url, obj_id, obj_type, field_id, extra_data) {
1342 function ajaxActionRevokePermission(url, obj_id, obj_type, field_id, extra_data) {
1382 var success = function (o) {
1343 var success = function (o) {
1383 $('#' + field_id).remove();
1344 $('#' + field_id).remove();
1384 };
1345 };
1385 var failure = function (o) {
1346 var failure = function (o) {
1386 alert(_TM['Failed to revoke permission'] + ": " + o.status);
1347 alert(_TM['Failed to revoke permission'] + ": " + o.status);
1387 };
1348 };
1388 var query_params = {};
1349 var query_params = {};
1389 // put extra data into POST
1350 // put extra data into POST
1390 if (extra_data !== undefined && (typeof extra_data === 'object')){
1351 if (extra_data !== undefined && (typeof extra_data === 'object')){
1391 for(var k in extra_data){
1352 for(var k in extra_data){
1392 query_params[k] = extra_data[k];
1353 query_params[k] = extra_data[k];
1393 }
1354 }
1394 }
1355 }
1395
1356
1396 if (obj_type=='user'){
1357 if (obj_type=='user'){
1397 query_params['user_id'] = obj_id;
1358 query_params['user_id'] = obj_id;
1398 query_params['obj_type'] = 'user';
1359 query_params['obj_type'] = 'user';
1399 }
1360 }
1400 else if (obj_type=='user_group'){
1361 else if (obj_type=='user_group'){
1401 query_params['user_group_id'] = obj_id;
1362 query_params['user_group_id'] = obj_id;
1402 query_params['obj_type'] = 'user_group';
1363 query_params['obj_type'] = 'user_group';
1403 }
1364 }
1404
1365
1405 ajaxPOST(url, query_params, success, failure);
1366 ajaxPOST(url, query_params, success, failure);
1406 };
1367 };
1407
1368
1408 /* Multi selectors */
1369 /* Multi selectors */
1409
1370
1410 var MultiSelectWidget = function(selected_id, available_id, form_id){
1371 var MultiSelectWidget = function(selected_id, available_id, form_id){
1411 var $availableselect = $('#' + available_id);
1372 var $availableselect = $('#' + available_id);
1412 var $selectedselect = $('#' + selected_id);
1373 var $selectedselect = $('#' + selected_id);
1413
1374
1414 //fill available only with those not in selected
1375 //fill available only with those not in selected
1415 var $selectedoptions = $selectedselect.children('option');
1376 var $selectedoptions = $selectedselect.children('option');
1416 $availableselect.children('option').filter(function(i, e){
1377 $availableselect.children('option').filter(function(i, e){
1417 for(var j = 0, node; node = $selectedoptions[j]; j++){
1378 for(var j = 0, node; node = $selectedoptions[j]; j++){
1418 if(node.value == e.value){
1379 if(node.value == e.value){
1419 return true;
1380 return true;
1420 }
1381 }
1421 }
1382 }
1422 return false;
1383 return false;
1423 }).remove();
1384 }).remove();
1424
1385
1425 $('#add_element').click(function(e){
1386 $('#add_element').click(function(e){
1426 $selectedselect.append($availableselect.children('option:selected'));
1387 $selectedselect.append($availableselect.children('option:selected'));
1427 });
1388 });
1428 $('#remove_element').click(function(e){
1389 $('#remove_element').click(function(e){
1429 $availableselect.append($selectedselect.children('option:selected'));
1390 $availableselect.append($selectedselect.children('option:selected'));
1430 });
1391 });
1431
1392
1432 $('#'+form_id).submit(function(){
1393 $('#'+form_id).submit(function(){
1433 $selectedselect.children('option').each(function(i, e){
1394 $selectedselect.children('option').each(function(i, e){
1434 e.selected = 'selected';
1395 e.selected = 'selected';
1435 });
1396 });
1436 });
1397 });
1437 }
1398 }
1438
1399
1439
1400
1440 /**
1401 /**
1441 Branch Sorting callback for select2, modifying the filtered result so prefix
1402 Branch Sorting callback for select2, modifying the filtered result so prefix
1442 matches come before matches in the line.
1403 matches come before matches in the line.
1443 **/
1404 **/
1444 var branchSort = function(results, container, query) {
1405 var branchSort = function(results, container, query) {
1445 if (query.term) {
1406 if (query.term) {
1446 return results.sort(function (a, b) {
1407 return results.sort(function (a, b) {
1447 // Put closed branches after open ones (a bit of a hack ...)
1408 // Put closed branches after open ones (a bit of a hack ...)
1448 var aClosed = a.text.indexOf("(closed)") > -1,
1409 var aClosed = a.text.indexOf("(closed)") > -1,
1449 bClosed = b.text.indexOf("(closed)") > -1;
1410 bClosed = b.text.indexOf("(closed)") > -1;
1450 if (aClosed && !bClosed) {
1411 if (aClosed && !bClosed) {
1451 return 1;
1412 return 1;
1452 }
1413 }
1453 if (bClosed && !aClosed) {
1414 if (bClosed && !aClosed) {
1454 return -1;
1415 return -1;
1455 }
1416 }
1456
1417
1457 // Put early (especially prefix) matches before later matches
1418 // Put early (especially prefix) matches before later matches
1458 var aPos = a.text.toLowerCase().indexOf(query.term.toLowerCase()),
1419 var aPos = a.text.toLowerCase().indexOf(query.term.toLowerCase()),
1459 bPos = b.text.toLowerCase().indexOf(query.term.toLowerCase());
1420 bPos = b.text.toLowerCase().indexOf(query.term.toLowerCase());
1460 if (aPos < bPos) {
1421 if (aPos < bPos) {
1461 return -1;
1422 return -1;
1462 }
1423 }
1463 if (bPos < aPos) {
1424 if (bPos < aPos) {
1464 return 1;
1425 return 1;
1465 }
1426 }
1466
1427
1467 // Default sorting
1428 // Default sorting
1468 if (a.text > b.text) {
1429 if (a.text > b.text) {
1469 return 1;
1430 return 1;
1470 }
1431 }
1471 if (a.text < b.text) {
1432 if (a.text < b.text) {
1472 return -1;
1433 return -1;
1473 }
1434 }
1474 return 0;
1435 return 0;
1475 });
1436 });
1476 }
1437 }
1477 return results;
1438 return results;
1478 };
1439 };
1479
1440
1480 var prefixFirstSort = function(results, container, query) {
1441 var prefixFirstSort = function(results, container, query) {
1481 if (query.term) {
1442 if (query.term) {
1482 return results.sort(function (a, b) {
1443 return results.sort(function (a, b) {
1483 // if parent node, no sorting
1444 // if parent node, no sorting
1484 if (a.children != undefined || b.children != undefined) {
1445 if (a.children != undefined || b.children != undefined) {
1485 return 0;
1446 return 0;
1486 }
1447 }
1487
1448
1488 // Put prefix matches before matches in the line
1449 // Put prefix matches before matches in the line
1489 var aPos = a.text.toLowerCase().indexOf(query.term.toLowerCase()),
1450 var aPos = a.text.toLowerCase().indexOf(query.term.toLowerCase()),
1490 bPos = b.text.toLowerCase().indexOf(query.term.toLowerCase());
1451 bPos = b.text.toLowerCase().indexOf(query.term.toLowerCase());
1491 if (aPos === 0 && bPos !== 0) {
1452 if (aPos === 0 && bPos !== 0) {
1492 return -1;
1453 return -1;
1493 }
1454 }
1494 if (bPos === 0 && aPos !== 0) {
1455 if (bPos === 0 && aPos !== 0) {
1495 return 1;
1456 return 1;
1496 }
1457 }
1497
1458
1498 // Default sorting
1459 // Default sorting
1499 if (a.text > b.text) {
1460 if (a.text > b.text) {
1500 return 1;
1461 return 1;
1501 }
1462 }
1502 if (a.text < b.text) {
1463 if (a.text < b.text) {
1503 return -1;
1464 return -1;
1504 }
1465 }
1505 return 0;
1466 return 0;
1506 });
1467 });
1507 }
1468 }
1508 return results;
1469 return results;
1509 };
1470 };
1510
1471
1511 /* Helper for jQuery DataTables */
1472 /* Helper for jQuery DataTables */
1512
1473
1513 var updateRowCountCallback = function updateRowCountCallback($elem, onlyDisplayed) {
1474 var updateRowCountCallback = function updateRowCountCallback($elem, onlyDisplayed) {
1514 return function drawCallback() {
1475 return function drawCallback() {
1515 var info = this.api().page.info(),
1476 var info = this.api().page.info(),
1516 count = onlyDisplayed === true ? info.recordsDisplay : info.recordsTotal;
1477 count = onlyDisplayed === true ? info.recordsDisplay : info.recordsTotal;
1517 $elem.html(count);
1478 $elem.html(count);
1518 }
1479 }
1519 };
1480 };
@@ -1,64 +1,63 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 %if c.users_log:
2 %if c.users_log:
3 <table class="table">
3 <table class="table">
4 <tr>
4 <tr>
5 <th class="left">${_('Username')}</th>
5 <th class="left">${_('Username')}</th>
6 <th class="left">${_('Action')}</th>
6 <th class="left">${_('Action')}</th>
7 <th class="left">${_('Repository')}</th>
7 <th class="left">${_('Repository')}</th>
8 <th class="left">${_('Date')}</th>
8 <th class="left">${_('Date')}</th>
9 <th class="left">${_('From IP')}</th>
9 <th class="left">${_('From IP')}</th>
10 </tr>
10 </tr>
11
11
12 %for cnt,l in enumerate(c.users_log):
12 %for cnt,l in enumerate(c.users_log):
13 <tr class="parity${cnt%2}">
13 <tr class="parity${cnt%2}">
14 <td>
14 <td>
15 %if l.user is not None:
15 %if l.user is not None:
16 ${h.link_to(l.user.username,h.url('edit_user', id=l.user.user_id))}
16 ${h.link_to(l.user.username,h.url('edit_user', id=l.user.user_id))}
17 %else:
17 %else:
18 ${l.username}
18 ${l.username}
19 %endif
19 %endif
20 </td>
20 </td>
21 <td>${h.action_parser(l)[0]()}
21 <td>${h.action_parser(l)[0]()}
22 <div class="journal_action_params">
22 <div class="journal_action_params">
23 ${h.literal(h.action_parser(l)[1]())}
23 ${h.literal(h.action_parser(l)[1]())}
24 </div>
24 </div>
25 </td>
25 </td>
26 <td>
26 <td>
27 %if l.repository is not None:
27 %if l.repository is not None:
28 ${h.link_to(l.repository.repo_name,h.url('summary_home',repo_name=l.repository.repo_name))}
28 ${h.link_to(l.repository.repo_name,h.url('summary_home',repo_name=l.repository.repo_name))}
29 %else:
29 %else:
30 ${l.repository_name}
30 ${l.repository_name}
31 %endif
31 %endif
32 </td>
32 </td>
33
33
34 <td>${h.fmt_date(l.action_date)}</td>
34 <td>${h.fmt_date(l.action_date)}</td>
35 <td>${l.user_ip}</td>
35 <td>${l.user_ip}</td>
36 </tr>
36 </tr>
37 %endfor
37 %endfor
38 </table>
38 </table>
39
39
40 <script type="text/javascript">
40 <script type="text/javascript">
41 $(document).ready(function(){
41 $(document).ready(function(){
42 var $user_log = $('#user_log');
42 var $user_log = $('#user_log');
43 $user_log.on('click','.pager_link',function(e){
43 $user_log.on('click','.pager_link',function(e){
44 asynchtml(e.target.href, $user_log, function(){
44 asynchtml(e.target.href, $user_log, function(){
45 show_more_event();
45 show_more_event();
46 tooltip_activate();
46 tooltip_activate();
47 show_changeset_tooltip();
48 });
47 });
49 e.preventDefault();
48 e.preventDefault();
50 });
49 });
51 $user_log.on('click','.show_more',function(e){
50 $user_log.on('click','.show_more',function(e){
52 var el = e.target;
51 var el = e.target;
53 $('#'+el.id.substring(1)).show();
52 $('#'+el.id.substring(1)).show();
54 $(el.parentNode).hide();
53 $(el.parentNode).hide();
55 });
54 });
56 });
55 });
57 </script>
56 </script>
58
57
59 <ul class="pagination">
58 <ul class="pagination">
60 ${c.users_log.pager()}
59 ${c.users_log.pager()}
61 </ul>
60 </ul>
62 %else:
61 %else:
63 ${_('No actions yet')}
62 ${_('No actions yet')}
64 %endif
63 %endif
@@ -1,136 +1,135 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <!DOCTYPE html>
2 <!DOCTYPE html>
3 <html xmlns="http://www.w3.org/1999/xhtml">
3 <html xmlns="http://www.w3.org/1999/xhtml">
4 <head>
4 <head>
5 <title><%block name="title"/><%block name="branding_title"/></title>
5 <title><%block name="title"/><%block name="branding_title"/></title>
6 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
6 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
7 <meta name="robots" content="index, nofollow"/>
7 <meta name="robots" content="index, nofollow"/>
8 <link rel="icon" href="${h.url('/images/favicon.ico')}" type="image/x-icon" />
8 <link rel="icon" href="${h.url('/images/favicon.ico')}" type="image/x-icon" />
9
9
10 ## CSS ###
10 ## CSS ###
11 <link rel="stylesheet" type="text/css" href="${h.url('/css/jquery.dataTables.css', ver=c.kallithea_version)}"/>
11 <link rel="stylesheet" type="text/css" href="${h.url('/css/jquery.dataTables.css', ver=c.kallithea_version)}"/>
12 <link rel="stylesheet" type="text/css" href="${h.url('/js/select2/select2.css', ver=c.kallithea_version)}"/>
12 <link rel="stylesheet" type="text/css" href="${h.url('/js/select2/select2.css', ver=c.kallithea_version)}"/>
13 <link rel="stylesheet" type="text/css" href="${h.url('/css/pygments.css', ver=c.kallithea_version)}"/>
13 <link rel="stylesheet" type="text/css" href="${h.url('/css/pygments.css', ver=c.kallithea_version)}"/>
14 <link rel="stylesheet" type="text/css" href="${h.url('/css/style.css', ver=c.kallithea_version)}" media="screen"/>
14 <link rel="stylesheet" type="text/css" href="${h.url('/css/style.css', ver=c.kallithea_version)}" media="screen"/>
15 <link rel="stylesheet" type="text/css" href="${h.url('/css/contextbar.css', ver=c.kallithea_version)}" media="screen"/>
15 <link rel="stylesheet" type="text/css" href="${h.url('/css/contextbar.css', ver=c.kallithea_version)}" media="screen"/>
16 <link rel="stylesheet" type="text/css" href="${h.url('/fontello/css/kallithea.css', ver=c.kallithea_version)}">
16 <link rel="stylesheet" type="text/css" href="${h.url('/fontello/css/kallithea.css', ver=c.kallithea_version)}">
17 <%block name="css_extra"/>
17 <%block name="css_extra"/>
18
18
19 ## JAVASCRIPT ##
19 ## JAVASCRIPT ##
20 <script type="text/javascript">
20 <script type="text/javascript">
21 ## JS translations map
21 ## JS translations map
22 var TRANSLATION_MAP = {
22 var TRANSLATION_MAP = {
23 'Add Another Comment':'${_("Add Another Comment")}',
23 'Add Another Comment':'${_("Add Another Comment")}',
24 'Stop following this repository':"${_('Stop following this repository')}",
24 'Stop following this repository':"${_('Stop following this repository')}",
25 'Start following this repository':"${_('Start following this repository')}",
25 'Start following this repository':"${_('Start following this repository')}",
26 'Group':"${_('Group')}",
26 'Group':"${_('Group')}",
27 'members':"${_('members')}",
27 'members':"${_('members')}",
28 'Loading ...':"${_('Loading ...')}",
28 'Loading ...':"${_('Loading ...')}",
29 'loading ...':"${_('loading ...')}",
29 'loading ...':"${_('loading ...')}",
30 'Search truncated': "${_('Search truncated')}",
30 'Search truncated': "${_('Search truncated')}",
31 'No matching files': "${_('No matching files')}",
31 'No matching files': "${_('No matching files')}",
32 'Open New Pull Request from {0}': "${_('Open New Pull Request from {0}')}",
32 'Open New Pull Request from {0}': "${_('Open New Pull Request from {0}')}",
33 'Open New Pull Request for {0} &rarr; {1}': "${h.literal(_('Open New Pull Request for {0} &rarr; {1}'))}",
33 'Open New Pull Request for {0} &rarr; {1}': "${h.literal(_('Open New Pull Request for {0} &rarr; {1}'))}",
34 'Show Selected Changesets {0} &rarr; {1}': "${h.literal(_('Show Selected Changesets {0} &rarr; {1}'))}",
34 'Show Selected Changesets {0} &rarr; {1}': "${h.literal(_('Show Selected Changesets {0} &rarr; {1}'))}",
35 'Selection Link': "${_('Selection Link')}",
35 'Selection Link': "${_('Selection Link')}",
36 'Collapse Diff': "${_('Collapse Diff')}",
36 'Collapse Diff': "${_('Collapse Diff')}",
37 'Expand Diff': "${_('Expand Diff')}",
37 'Expand Diff': "${_('Expand Diff')}",
38 'Failed to revoke permission': "${_('Failed to revoke permission')}",
38 'Failed to revoke permission': "${_('Failed to revoke permission')}",
39 'Confirm to revoke permission for {0}: {1} ?': "${_('Confirm to revoke permission for {0}: {1} ?')}",
39 'Confirm to revoke permission for {0}: {1} ?': "${_('Confirm to revoke permission for {0}: {1} ?')}",
40 'Enabled': "${_('Enabled')}",
40 'Enabled': "${_('Enabled')}",
41 'Disabled': "${_('Disabled')}",
41 'Disabled': "${_('Disabled')}",
42 'Select changeset': "${_('Select changeset')}",
42 'Select changeset': "${_('Select changeset')}",
43 'Specify changeset': "${_('Specify changeset')}",
43 'Specify changeset': "${_('Specify changeset')}",
44 'MSG_SORTASC': "${_('Click to sort ascending')}",
44 'MSG_SORTASC': "${_('Click to sort ascending')}",
45 'MSG_SORTDESC': "${_('Click to sort descending')}",
45 'MSG_SORTDESC': "${_('Click to sort descending')}",
46 'MSG_EMPTY': "${_('No records found.')}",
46 'MSG_EMPTY': "${_('No records found.')}",
47 'MSG_ERROR': "${_('Data error.')}",
47 'MSG_ERROR': "${_('Data error.')}",
48 'MSG_LOADING': "${_('Loading...')}"
48 'MSG_LOADING': "${_('Loading...')}"
49 };
49 };
50 var _TM = TRANSLATION_MAP;
50 var _TM = TRANSLATION_MAP;
51
51
52 var TOGGLE_FOLLOW_URL = "${h.url('toggle_following')}";
52 var TOGGLE_FOLLOW_URL = "${h.url('toggle_following')}";
53
53
54 var REPO_NAME = "";
54 var REPO_NAME = "";
55 %if hasattr(c, 'repo_name'):
55 %if hasattr(c, 'repo_name'):
56 var REPO_NAME = "${c.repo_name}";
56 var REPO_NAME = "${c.repo_name}";
57 %endif
57 %endif
58
58
59 var _authentication_token = "${h.authentication_token()}";
59 var _authentication_token = "${h.authentication_token()}";
60 </script>
60 </script>
61 <script type="text/javascript" src="${h.url('/js/yui.2.9.js', ver=c.kallithea_version)}"></script>
61 <script type="text/javascript" src="${h.url('/js/yui.2.9.js', ver=c.kallithea_version)}"></script>
62 <script type="text/javascript" src="${h.url('/js/jquery.min.js', ver=c.kallithea_version)}"></script>
62 <script type="text/javascript" src="${h.url('/js/jquery.min.js', ver=c.kallithea_version)}"></script>
63 <script type="text/javascript" src="${h.url('/js/jquery.dataTables.min.js', ver=c.kallithea_version)}"></script>
63 <script type="text/javascript" src="${h.url('/js/jquery.dataTables.min.js', ver=c.kallithea_version)}"></script>
64 <script type="text/javascript" src="${h.url('/js/bootstrap.js', ver=c.kallithea_version)}"></script>
64 <script type="text/javascript" src="${h.url('/js/bootstrap.js', ver=c.kallithea_version)}"></script>
65 <script type="text/javascript" src="${h.url('/js/select2/select2.js', ver=c.kallithea_version)}"></script>
65 <script type="text/javascript" src="${h.url('/js/select2/select2.js', ver=c.kallithea_version)}"></script>
66 <script type="text/javascript" src="${h.url('/js/yui.flot.js', ver=c.kallithea_version)}"></script>
66 <script type="text/javascript" src="${h.url('/js/yui.flot.js', ver=c.kallithea_version)}"></script>
67 <script type="text/javascript" src="${h.url('/js/native.history.js', ver=c.kallithea_version)}"></script>
67 <script type="text/javascript" src="${h.url('/js/native.history.js', ver=c.kallithea_version)}"></script>
68 <script type="text/javascript" src="${h.url('/js/base.js', ver=c.kallithea_version)}"></script>
68 <script type="text/javascript" src="${h.url('/js/base.js', ver=c.kallithea_version)}"></script>
69 ## EXTRA FOR JS
69 ## EXTRA FOR JS
70 <%block name="js_extra"/>
70 <%block name="js_extra"/>
71 <script type="text/javascript">
71 <script type="text/javascript">
72 (function(window,undefined){
72 (function(window,undefined){
73 var History = window.History; // Note: We are using a capital H instead of a lower h
73 var History = window.History; // Note: We are using a capital H instead of a lower h
74 if ( !History.enabled ) {
74 if ( !History.enabled ) {
75 // History.js is disabled for this browser.
75 // History.js is disabled for this browser.
76 // This is because we can optionally choose to support HTML4 browsers or not.
76 // This is because we can optionally choose to support HTML4 browsers or not.
77 return false;
77 return false;
78 }
78 }
79 })(window);
79 })(window);
80
80
81 $(document).ready(function(){
81 $(document).ready(function(){
82 tooltip_activate();
82 tooltip_activate();
83 show_more_event();
83 show_more_event();
84 show_changeset_tooltip();
85 // routes registration
84 // routes registration
86 pyroutes.register('home', "${h.url('home')}", []);
85 pyroutes.register('home', "${h.url('home')}", []);
87 pyroutes.register('new_gist', "${h.url('new_gist')}", []);
86 pyroutes.register('new_gist', "${h.url('new_gist')}", []);
88 pyroutes.register('gists', "${h.url('gists')}", []);
87 pyroutes.register('gists', "${h.url('gists')}", []);
89 pyroutes.register('new_repo', "${h.url('new_repo')}", []);
88 pyroutes.register('new_repo', "${h.url('new_repo')}", []);
90
89
91 pyroutes.register('summary_home', "${h.url('summary_home', repo_name='%(repo_name)s')}", ['repo_name']);
90 pyroutes.register('summary_home', "${h.url('summary_home', repo_name='%(repo_name)s')}", ['repo_name']);
92 pyroutes.register('changelog_home', "${h.url('changelog_home', repo_name='%(repo_name)s')}", ['repo_name']);
91 pyroutes.register('changelog_home', "${h.url('changelog_home', repo_name='%(repo_name)s')}", ['repo_name']);
93 pyroutes.register('files_home', "${h.url('files_home', repo_name='%(repo_name)s',revision='%(revision)s',f_path='%(f_path)s')}", ['repo_name', 'revision', 'f_path']);
92 pyroutes.register('files_home', "${h.url('files_home', repo_name='%(repo_name)s',revision='%(revision)s',f_path='%(f_path)s')}", ['repo_name', 'revision', 'f_path']);
94 pyroutes.register('edit_repo', "${h.url('edit_repo', repo_name='%(repo_name)s')}", ['repo_name']);
93 pyroutes.register('edit_repo', "${h.url('edit_repo', repo_name='%(repo_name)s')}", ['repo_name']);
95 pyroutes.register('edit_repo_perms', "${h.url('edit_repo_perms', repo_name='%(repo_name)s')}", ['repo_name']);
94 pyroutes.register('edit_repo_perms', "${h.url('edit_repo_perms', repo_name='%(repo_name)s')}", ['repo_name']);
96 pyroutes.register('pullrequest_home', "${h.url('pullrequest_home', repo_name='%(repo_name)s')}", ['repo_name']);
95 pyroutes.register('pullrequest_home', "${h.url('pullrequest_home', repo_name='%(repo_name)s')}", ['repo_name']);
97
96
98 pyroutes.register('toggle_following', "${h.url('toggle_following')}");
97 pyroutes.register('toggle_following', "${h.url('toggle_following')}");
99 pyroutes.register('changeset_info', "${h.url('changeset_info', repo_name='%(repo_name)s', revision='%(revision)s')}", ['repo_name', 'revision']);
98 pyroutes.register('changeset_info', "${h.url('changeset_info', repo_name='%(repo_name)s', revision='%(revision)s')}", ['repo_name', 'revision']);
100 pyroutes.register('repo_size', "${h.url('repo_size', repo_name='%(repo_name)s')}", ['repo_name']);
99 pyroutes.register('repo_size', "${h.url('repo_size', repo_name='%(repo_name)s')}", ['repo_name']);
101 pyroutes.register('repo_refs_data', "${h.url('repo_refs_data', repo_name='%(repo_name)s')}", ['repo_name']);
100 pyroutes.register('repo_refs_data', "${h.url('repo_refs_data', repo_name='%(repo_name)s')}", ['repo_name']);
102 });
101 });
103 </script>
102 </script>
104
103
105 <%block name="head_extra"/>
104 <%block name="head_extra"/>
106 </head>
105 </head>
107 <body>
106 <body>
108 <nav class="navbar navbar-inverse">
107 <nav class="navbar navbar-inverse">
109 <div>
108 <div>
110 <div class="navbar-header" id="logo">
109 <div class="navbar-header" id="logo">
111 <a class="navbar-brand" href="${h.url('home')}">
110 <a class="navbar-brand" href="${h.url('home')}">
112 <img class="pull-left" src="${h.url('/images/kallithea-logo.svg')}" alt="Kallithea"/>
111 <img class="pull-left" src="${h.url('/images/kallithea-logo.svg')}" alt="Kallithea"/>
113 %if c.site_name:
112 %if c.site_name:
114 <span class="branding">${c.site_name}</span>
113 <span class="branding">${c.site_name}</span>
115 %endif
114 %endif
116 </a>
115 </a>
117 <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false">
116 <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false">
118 <span class="sr-only">Toggle navigation</span>
117 <span class="sr-only">Toggle navigation</span>
119 <span class="icon-bar"></span>
118 <span class="icon-bar"></span>
120 <span class="icon-bar"></span>
119 <span class="icon-bar"></span>
121 <span class="icon-bar"></span>
120 <span class="icon-bar"></span>
122 </button>
121 </button>
123 </div>
122 </div>
124 <div id="navbar" class="navbar-collapse collapse">
123 <div id="navbar" class="navbar-collapse collapse">
125 <%block name="header_menu"/>
124 <%block name="header_menu"/>
126 </div>
125 </div>
127 </div>
126 </div>
128 </nav>
127 </nav>
129
128
130 ${next.body()}
129 ${next.body()}
131
130
132 %if c.ga_code:
131 %if c.ga_code:
133 ${h.literal(c.ga_code)}
132 ${h.literal(c.ga_code)}
134 %endif
133 %endif
135 </body>
134 </body>
136 </html>
135 </html>
@@ -1,161 +1,161 b''
1 ## DATA TABLE RE USABLE ELEMENTS
1 ## DATA TABLE RE USABLE ELEMENTS
2 ## usage:
2 ## usage:
3 ## <%namespace name="dt" file="/data_table/_dt_elements.html"/>
3 ## <%namespace name="dt" file="/data_table/_dt_elements.html"/>
4
4
5 <%namespace name="base" file="/base/base.html"/>
5 <%namespace name="base" file="/base/base.html"/>
6
6
7 <%def name="repo_name(name,rtype,rstate,private,fork_of,short_name=False,admin=False)">
7 <%def name="repo_name(name,rtype,rstate,private,fork_of,short_name=False,admin=False)">
8 <%
8 <%
9 def get_name(name,short_name=short_name):
9 def get_name(name,short_name=short_name):
10 if short_name:
10 if short_name:
11 return name.split('/')[-1]
11 return name.split('/')[-1]
12 else:
12 else:
13 return name
13 return name
14 %>
14 %>
15 <div class="dt_repo ${'dt_repo_pending' if rstate == 'repo_state_pending' else ''}">
15 <div class="dt_repo ${'dt_repo_pending' if rstate == 'repo_state_pending' else ''}">
16 ##NAME
16 ##NAME
17 <a href="${h.url('edit_repo' if admin else 'summary_home', repo_name=name)}">
17 <a href="${h.url('edit_repo' if admin else 'summary_home', repo_name=name)}">
18
18
19 ##TYPE OF REPO
19 ##TYPE OF REPO
20 ${base.repotag(rtype)}
20 ${base.repotag(rtype)}
21
21
22 ##PRIVATE/PUBLIC
22 ##PRIVATE/PUBLIC
23 %if private and c.visual.show_private_icon:
23 %if private and c.visual.show_private_icon:
24 <i class="icon-keyhole-circled" title="${_('Private repository')}"></i>
24 <i class="icon-keyhole-circled" title="${_('Private repository')}"></i>
25 %elif not private and c.visual.show_public_icon:
25 %elif not private and c.visual.show_public_icon:
26 <i class="icon-globe" title="${_('Public repository')}"></i>
26 <i class="icon-globe" title="${_('Public repository')}"></i>
27 %else:
27 %else:
28 <span style="margin: 0px 8px 0px 8px"></span>
28 <span style="margin: 0px 8px 0px 8px"></span>
29 %endif
29 %endif
30 <span class="dt_repo_name">${get_name(name)}</span>
30 <span class="dt_repo_name">${get_name(name)}</span>
31 </a>
31 </a>
32 %if fork_of:
32 %if fork_of:
33 <a href="${h.url('summary_home',repo_name=fork_of.repo_name)}"><i class="icon-fork"></i></a>
33 <a href="${h.url('summary_home',repo_name=fork_of.repo_name)}"><i class="icon-fork"></i></a>
34 %endif
34 %endif
35 %if rstate == 'repo_state_pending':
35 %if rstate == 'repo_state_pending':
36 <i class="icon-wrench" title="${_('Repository creation in progress...')}"></i>
36 <i class="icon-wrench" title="${_('Repository creation in progress...')}"></i>
37 %endif
37 %endif
38 </div>
38 </div>
39 </%def>
39 </%def>
40
40
41 <%def name="last_change(last_change)">
41 <%def name="last_change(last_change)">
42 <span data-toggle="tooltip" title="${h.fmt_date(last_change)}" date="${last_change}">${h.age(last_change)}</span>
42 <span data-toggle="tooltip" title="${h.fmt_date(last_change)}" date="${last_change}">${h.age(last_change)}</span>
43 </%def>
43 </%def>
44
44
45 <%def name="revision(name,rev,tip,author,last_msg)">
45 <%def name="revision(name,rev,tip,author,last_msg)">
46 <div>
46 <div>
47 %if rev >= 0:
47 %if rev >= 0:
48 <a data-toggle="tooltip" title="${'%s:\n\n%s' % (h.escape(author), h.escape(last_msg))}" class="revision-link safe-html-title" href="${h.url('changeset_home',repo_name=name,revision=tip)}">${'r%s:%s' % (rev,h.short_id(tip))}</a>
48 <a data-toggle="popover" title="${author | entity}" data-content="${last_msg | entity}" class="hash" href="${h.url('changeset_home',repo_name=name,revision=tip)}">${'r%s:%s' % (rev,h.short_id(tip))}</a>
49 %else:
49 %else:
50 ${_('No changesets yet')}
50 ${_('No changesets yet')}
51 %endif
51 %endif
52 </div>
52 </div>
53 </%def>
53 </%def>
54
54
55 <%def name="rss(name)">
55 <%def name="rss(name)">
56 %if c.authuser.username != 'default':
56 %if c.authuser.username != 'default':
57 <a title="${_('Subscribe to %s rss feed')% name}" href="${h.url('rss_feed_home',repo_name=name,api_key=c.authuser.api_key)}"><i class="icon-rss-squared"></i></a>
57 <a title="${_('Subscribe to %s rss feed')% name}" href="${h.url('rss_feed_home',repo_name=name,api_key=c.authuser.api_key)}"><i class="icon-rss-squared"></i></a>
58 %else:
58 %else:
59 <a title="${_('Subscribe to %s rss feed')% name}" href="${h.url('rss_feed_home',repo_name=name)}"><i class="icon-rss-squared"></i></a>
59 <a title="${_('Subscribe to %s rss feed')% name}" href="${h.url('rss_feed_home',repo_name=name)}"><i class="icon-rss-squared"></i></a>
60 %endif
60 %endif
61 </%def>
61 </%def>
62
62
63 <%def name="atom(name)">
63 <%def name="atom(name)">
64 %if c.authuser.username != 'default':
64 %if c.authuser.username != 'default':
65 <a title="${_('Subscribe to %s atom feed')% name}" href="${h.url('atom_feed_home',repo_name=name,api_key=c.authuser.api_key)}"><i class="icon-rss-squared"></i></a>
65 <a title="${_('Subscribe to %s atom feed')% name}" href="${h.url('atom_feed_home',repo_name=name,api_key=c.authuser.api_key)}"><i class="icon-rss-squared"></i></a>
66 %else:
66 %else:
67 <a title="${_('Subscribe to %s atom feed')% name}" href="${h.url('atom_feed_home',repo_name=name)}"><i class="icon-rss-squared"></i></a>
67 <a title="${_('Subscribe to %s atom feed')% name}" href="${h.url('atom_feed_home',repo_name=name)}"><i class="icon-rss-squared"></i></a>
68 %endif
68 %endif
69 </%def>
69 </%def>
70
70
71 <%def name="repo_actions(repo_name, super_user=True)">
71 <%def name="repo_actions(repo_name, super_user=True)">
72 <div>
72 <div>
73 <div class="grid_edit pull-left">
73 <div class="grid_edit pull-left">
74 <a href="${h.url('edit_repo',repo_name=repo_name)}" title="${_('Edit')}">
74 <a href="${h.url('edit_repo',repo_name=repo_name)}" title="${_('Edit')}">
75 <i class="icon-pencil"></i> ${h.submit('edit_%s' % repo_name,_('Edit'),class_="btn btn-default btn-xs")}
75 <i class="icon-pencil"></i> ${h.submit('edit_%s' % repo_name,_('Edit'),class_="btn btn-default btn-xs")}
76 </a>
76 </a>
77 </div>
77 </div>
78 <div class="grid_delete pull-left">
78 <div class="grid_delete pull-left">
79 ${h.form(h.url('delete_repo', repo_name=repo_name))}
79 ${h.form(h.url('delete_repo', repo_name=repo_name))}
80 <i class="icon-minus-circled" style="color:#FF4444"></i>
80 <i class="icon-minus-circled" style="color:#FF4444"></i>
81 ${h.submit('remove_%s' % repo_name,_('Delete'),class_="btn btn-default btn-xs",
81 ${h.submit('remove_%s' % repo_name,_('Delete'),class_="btn btn-default btn-xs",
82 onclick="return confirm('"+_('Confirm to delete this repository: %s') % repo_name+"');")}
82 onclick="return confirm('"+_('Confirm to delete this repository: %s') % repo_name+"');")}
83 ${h.end_form()}
83 ${h.end_form()}
84 </div>
84 </div>
85 </div>
85 </div>
86 </%def>
86 </%def>
87
87
88 <%def name="repo_state(repo_state)">
88 <%def name="repo_state(repo_state)">
89 <div>
89 <div>
90 %if repo_state == u'repo_state_pending':
90 %if repo_state == u'repo_state_pending':
91 <div class="label label-info">${_('Creating')}</div>
91 <div class="label label-info">${_('Creating')}</div>
92 %elif repo_state == u'repo_state_created':
92 %elif repo_state == u'repo_state_created':
93 <div class="label label-success">${_('Created')}</div>
93 <div class="label label-success">${_('Created')}</div>
94 %else:
94 %else:
95 <div class="label label-danger" title="${repo_state}">invalid</div>
95 <div class="label label-danger" title="${repo_state}">invalid</div>
96 %endif
96 %endif
97 </div>
97 </div>
98 </%def>
98 </%def>
99
99
100 <%def name="user_actions(user_id, username)">
100 <%def name="user_actions(user_id, username)">
101 <div class="grid_edit pull-left">
101 <div class="grid_edit pull-left">
102 <a href="${h.url('edit_user',id=user_id)}" title="${_('Edit')}">
102 <a href="${h.url('edit_user',id=user_id)}" title="${_('Edit')}">
103 <i class="icon-pencil"></i> ${h.submit('edit_%s' % username,_('Edit'),class_="btn btn-default btn-xs")}
103 <i class="icon-pencil"></i> ${h.submit('edit_%s' % username,_('Edit'),class_="btn btn-default btn-xs")}
104 </a>
104 </a>
105 </div>
105 </div>
106 <div class="grid_delete pull-left">
106 <div class="grid_delete pull-left">
107 ${h.form(h.url('delete_user', id=user_id))}
107 ${h.form(h.url('delete_user', id=user_id))}
108 <i class="icon-minus-circled" style="color:#FF4444"></i>
108 <i class="icon-minus-circled" style="color:#FF4444"></i>
109 ${h.submit('remove_',_('Delete'),id="remove_user_%s" % user_id, class_="btn btn-default btn-xs",
109 ${h.submit('remove_',_('Delete'),id="remove_user_%s" % user_id, class_="btn btn-default btn-xs",
110 onclick="return confirm('"+_('Confirm to delete this user: %s') % username+"');")}
110 onclick="return confirm('"+_('Confirm to delete this user: %s') % username+"');")}
111 ${h.end_form()}
111 ${h.end_form()}
112 </div>
112 </div>
113 </%def>
113 </%def>
114
114
115 <%def name="user_group_actions(user_group_id, user_group_name)">
115 <%def name="user_group_actions(user_group_id, user_group_name)">
116 <div class="grid_edit pull-left">
116 <div class="grid_edit pull-left">
117 <a href="${h.url('edit_users_group', id=user_group_id)}" title="${_('Edit')}">
117 <a href="${h.url('edit_users_group', id=user_group_id)}" title="${_('Edit')}">
118 <i class="icon-pencil"></i> ${h.submit('edit_%s' % user_group_name,_('Edit'),class_="btn btn-default btn-xs", id_="submit_user_group_edit")}
118 <i class="icon-pencil"></i> ${h.submit('edit_%s' % user_group_name,_('Edit'),class_="btn btn-default btn-xs", id_="submit_user_group_edit")}
119 </a>
119 </a>
120 </div>
120 </div>
121 <div class="grid_delete pull-left">
121 <div class="grid_delete pull-left">
122 ${h.form(h.url('delete_users_group', id=user_group_id))}
122 ${h.form(h.url('delete_users_group', id=user_group_id))}
123 <i class="icon-minus-circled" style="color:#FF4444"></i>
123 <i class="icon-minus-circled" style="color:#FF4444"></i>
124 ${h.submit('remove_',_('Delete'),id="remove_group_%s" % user_group_id, class_="btn btn-default btn-xs",
124 ${h.submit('remove_',_('Delete'),id="remove_group_%s" % user_group_id, class_="btn btn-default btn-xs",
125 onclick="return confirm('"+_('Confirm to delete this user group: %s') % user_group_name+"');")}
125 onclick="return confirm('"+_('Confirm to delete this user group: %s') % user_group_name+"');")}
126 ${h.end_form()}
126 ${h.end_form()}
127 </div>
127 </div>
128 </%def>
128 </%def>
129
129
130 <%def name="repo_group_actions(repo_group_id, repo_group_name, gr_count)">
130 <%def name="repo_group_actions(repo_group_id, repo_group_name, gr_count)">
131 <div class="grid_edit pull-left">
131 <div class="grid_edit pull-left">
132 <a href="${h.url('edit_repo_group',group_name=repo_group_name)}" title="${_('Edit')}">
132 <a href="${h.url('edit_repo_group',group_name=repo_group_name)}" title="${_('Edit')}">
133 <i class="icon-pencil"></i> ${h.submit('edit_%s' % repo_group_name, _('Edit'),class_="btn btn-default btn-xs")}
133 <i class="icon-pencil"></i> ${h.submit('edit_%s' % repo_group_name, _('Edit'),class_="btn btn-default btn-xs")}
134 </a>
134 </a>
135 </div>
135 </div>
136 <div class="grid_delete pull-left">
136 <div class="grid_delete pull-left">
137 ${h.form(h.url('delete_repos_group', group_name=repo_group_name))}
137 ${h.form(h.url('delete_repos_group', group_name=repo_group_name))}
138 <i class="icon-minus-circled" style="color:#FF4444"></i>
138 <i class="icon-minus-circled" style="color:#FF4444"></i>
139 ${h.submit('remove_%s' % repo_group_name,_('Delete'),class_="btn btn-default btn-xs",
139 ${h.submit('remove_%s' % repo_group_name,_('Delete'),class_="btn btn-default btn-xs",
140 onclick="return confirm('"+ungettext('Confirm to delete this group: %s with %s repository','Confirm to delete this group: %s with %s repositories',gr_count) % (repo_group_name, gr_count)+"');")}
140 onclick="return confirm('"+ungettext('Confirm to delete this group: %s with %s repository','Confirm to delete this group: %s with %s repositories',gr_count) % (repo_group_name, gr_count)+"');")}
141 ${h.end_form()}
141 ${h.end_form()}
142 </div>
142 </div>
143 </%def>
143 </%def>
144
144
145 <%def name="user_name(user_id, username)">
145 <%def name="user_name(user_id, username)">
146 ${h.link_to(username,h.url('edit_user', id=user_id))}
146 ${h.link_to(username,h.url('edit_user', id=user_id))}
147 </%def>
147 </%def>
148
148
149 <%def name="repo_group_name(repo_group_name, children_groups)">
149 <%def name="repo_group_name(repo_group_name, children_groups)">
150 <div class="text-nowrap">
150 <div class="text-nowrap">
151 <a href="${h.url('repos_group_home',group_name=repo_group_name)}">
151 <a href="${h.url('repos_group_home',group_name=repo_group_name)}">
152 <i class="icon-folder" title="${_('Repository group')}"></i> ${h.literal(' &raquo; '.join(children_groups))}</a>
152 <i class="icon-folder" title="${_('Repository group')}"></i> ${h.literal(' &raquo; '.join(children_groups))}</a>
153 </div>
153 </div>
154 </%def>
154 </%def>
155
155
156 <%def name="user_group_name(user_group_id, user_group_name)">
156 <%def name="user_group_name(user_group_id, user_group_name)">
157 <div class="text-nowrap">
157 <div class="text-nowrap">
158 <a href="${h.url('edit_users_group', id=user_group_id)}">
158 <a href="${h.url('edit_users_group', id=user_group_id)}">
159 <i class="icon-users" title="${_('User group')}"></i> ${user_group_name}</a>
159 <i class="icon-users" title="${_('User group')}"></i> ${user_group_name}</a>
160 </div>
160 </div>
161 </%def>
161 </%def>
@@ -1,99 +1,99 b''
1 <div id="node_history" style="padding: 0px 0px 10px 0px">
1 <div id="node_history" style="padding: 0px 0px 10px 0px">
2 <div>
2 <div>
3 <div class="pull-left">
3 <div class="pull-left">
4 ${h.form(h.url('files_diff_home',repo_name=c.repo_name,f_path=c.f_path),method='get')}
4 ${h.form(h.url('files_diff_home',repo_name=c.repo_name,f_path=c.f_path),method='get')}
5 ${h.hidden('diff2',c.changeset.raw_id)}
5 ${h.hidden('diff2',c.changeset.raw_id)}
6 ${h.hidden('diff1')}
6 ${h.hidden('diff1')}
7 ${h.submit('diff',_('Diff to Revision'),class_="btn btn-default btn-sm")}
7 ${h.submit('diff',_('Diff to Revision'),class_="btn btn-default btn-sm")}
8 ${h.submit('show_rev',_('Show at Revision'),class_="btn btn-default btn-sm")}
8 ${h.submit('show_rev',_('Show at Revision'),class_="btn btn-default btn-sm")}
9 ${h.hidden('annotate', c.annotate)}
9 ${h.hidden('annotate', c.annotate)}
10 ${h.link_to(_('Show Full History'),h.url('changelog_file_home',repo_name=c.repo_name, revision=c.changeset.raw_id, f_path=c.f_path),class_="btn btn-default btn-sm")}
10 ${h.link_to(_('Show Full History'),h.url('changelog_file_home',repo_name=c.repo_name, revision=c.changeset.raw_id, f_path=c.f_path),class_="btn btn-default btn-sm")}
11 ${h.link_to(_('Show Authors'),'#',class_="btn btn-default btn-sm" ,id="show_authors")}
11 ${h.link_to(_('Show Authors'),'#',class_="btn btn-default btn-sm" ,id="show_authors")}
12 ${h.end_form()}
12 ${h.end_form()}
13 </div>
13 </div>
14 <div id="file_authors" class="file_author" style="clear:both; display: none"></div>
14 <div id="file_authors" class="file_author" style="clear:both; display: none"></div>
15 </div>
15 </div>
16 <div style="clear:both"></div>
16 <div style="clear:both"></div>
17 </div>
17 </div>
18
18
19
19
20 <div id="body" class="codeblock">
20 <div id="body" class="codeblock">
21 <div class="code-header">
21 <div class="code-header">
22 <div class="stats">
22 <div class="stats">
23 <div class="pull-left">
23 <div class="pull-left">
24 <div class="left img"><i class="icon-doc-inv"></i></div>
24 <div class="left img"><i class="icon-doc-inv"></i></div>
25 <div class="left item"><pre data-toggle="tooltip" title="${h.fmt_date(c.changeset.date)}">${h.link_to(h.show_id(c.changeset),h.url('changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}</pre></div>
25 <div class="left item"><pre data-toggle="tooltip" title="${h.fmt_date(c.changeset.date)}">${h.link_to(h.show_id(c.changeset),h.url('changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}</pre></div>
26 <div class="left item"><pre>${h.format_byte_size(c.file.size,binary=True)}</pre></div>
26 <div class="left item"><pre>${h.format_byte_size(c.file.size,binary=True)}</pre></div>
27 <div class="left item last"><pre>${c.file.mimetype}</pre></div>
27 <div class="left item last"><pre>${c.file.mimetype}</pre></div>
28 </div>
28 </div>
29 <div class="pull-right buttons">
29 <div class="pull-right buttons">
30 %if c.annotate:
30 %if c.annotate:
31 ${h.link_to(_('Show Source'), h.url('files_home', repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path),class_="btn btn-default btn-xs")}
31 ${h.link_to(_('Show Source'), h.url('files_home', repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path),class_="btn btn-default btn-xs")}
32 %else:
32 %else:
33 ${h.link_to(_('Show Annotation'),h.url('files_annotate_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path),class_="btn btn-default btn-xs")}
33 ${h.link_to(_('Show Annotation'),h.url('files_annotate_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path),class_="btn btn-default btn-xs")}
34 %endif
34 %endif
35 ${h.link_to(_('Show as Raw'),h.url('files_raw_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path),class_="btn btn-default btn-xs")}
35 ${h.link_to(_('Show as Raw'),h.url('files_raw_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path),class_="btn btn-default btn-xs")}
36 ${h.link_to(_('Download as Raw'),h.url('files_rawfile_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path),class_="btn btn-default btn-xs")}
36 ${h.link_to(_('Download as Raw'),h.url('files_rawfile_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path),class_="btn btn-default btn-xs")}
37 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name):
37 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name):
38 %if c.on_branch_head and not c.file.is_binary:
38 %if c.on_branch_head and not c.file.is_binary:
39 ${h.link_to(_('Edit on Branch: %s') % c.changeset.branch, h.url('files_edit_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path, anchor='edit'),class_="btn btn-default btn-xs")}
39 ${h.link_to(_('Edit on Branch: %s') % c.changeset.branch, h.url('files_edit_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path, anchor='edit'),class_="btn btn-default btn-xs")}
40 ${h.link_to(_('Delete'), h.url('files_delete_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path, anchor='edit'),class_="btn btn-danger btn-xs")}
40 ${h.link_to(_('Delete'), h.url('files_delete_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path, anchor='edit'),class_="btn btn-danger btn-xs")}
41 %elif c.on_branch_head and c.file.is_binary:
41 %elif c.on_branch_head and c.file.is_binary:
42 ${h.link_to(_('Edit'), '#', class_="btn btn-default btn-xs disabled tooltip", title=_('Editing binary files not allowed'))}
42 ${h.link_to(_('Edit'), '#', class_="btn btn-default btn-xs disabled", title=_('Editing binary files not allowed'),**{'data-toggle':'tooltip'})}
43 ${h.link_to(_('Delete'), h.url('files_delete_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path, anchor='edit'),class_="btn btn-danger btn-xs")}
43 ${h.link_to(_('Delete'), h.url('files_delete_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path, anchor='edit'),class_="btn btn-danger btn-xs")}
44 %else:
44 %else:
45 ${h.link_to(_('Edit'), '#', class_="btn btn-default btn-xs disabled tooltip", title=_('Editing files allowed only when on branch head revision'))}
45 ${h.link_to(_('Edit'), '#', class_="btn btn-default btn-xs disabled", title=_('Editing files allowed only when on branch head revision'),**{'data-toggle':'tooltip'})}
46 ${h.link_to(_('Delete'), '#', class_="btn btn-danger btn-xs disabled tooltip", title=_('Deleting files allowed only when on branch head revision'))}
46 ${h.link_to(_('Delete'), '#', class_="btn btn-danger btn-xs disabled", title=_('Deleting files allowed only when on branch head revision'),**{'data-toggle':'tooltip'})}
47 %endif
47 %endif
48 %endif
48 %endif
49 </div>
49 </div>
50 </div>
50 </div>
51 <div class="author">
51 <div class="author">
52 ${h.gravatar_div(h.email_or_none(c.changeset.author), size=16)}
52 ${h.gravatar_div(h.email_or_none(c.changeset.author), size=16)}
53 <div title="${c.changeset.author}" class="user">${h.person(c.changeset.author)}</div>
53 <div title="${c.changeset.author}" class="user">${h.person(c.changeset.author)}</div>
54 </div>
54 </div>
55 <div class="commit">${h.urlify_text(c.changeset.message,c.repo_name)}</div>
55 <div class="commit">${h.urlify_text(c.changeset.message,c.repo_name)}</div>
56 </div>
56 </div>
57 <div class="code-body">
57 <div class="code-body">
58 %if c.file.is_browser_compatible_image():
58 %if c.file.is_browser_compatible_image():
59 <img src="${h.url('files_raw_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path)}" class="img-preview"/>
59 <img src="${h.url('files_raw_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path)}" class="img-preview"/>
60 %elif c.file.is_binary:
60 %elif c.file.is_binary:
61 <div style="padding:5px">
61 <div style="padding:5px">
62 ${_('Binary file (%s)') % c.file.mimetype}
62 ${_('Binary file (%s)') % c.file.mimetype}
63 </div>
63 </div>
64 %else:
64 %else:
65 %if c.file.size < c.cut_off_limit or c.fulldiff:
65 %if c.file.size < c.cut_off_limit or c.fulldiff:
66 %if c.annotate:
66 %if c.annotate:
67 ${h.pygmentize_annotation(c.repo_name,c.file,linenos=True,anchorlinenos=True,lineanchors='L',cssclass="code-highlight")}
67 ${h.pygmentize_annotation(c.repo_name,c.file,linenos=True,anchorlinenos=True,lineanchors='L',cssclass="code-highlight")}
68 %else:
68 %else:
69 ${h.pygmentize(c.file,linenos=True,anchorlinenos=True,lineanchors='L',cssclass="code-highlight")}
69 ${h.pygmentize(c.file,linenos=True,anchorlinenos=True,lineanchors='L',cssclass="code-highlight")}
70 %endif
70 %endif
71 %else:
71 %else:
72 <h4>
72 <h4>
73 ${_('File is too big to display.')}
73 ${_('File is too big to display.')}
74 %if c.annotate:
74 %if c.annotate:
75 ${h.link_to(_('Show full annotation anyway.'), h.url.current(fulldiff=1, **request.GET.mixed()))}
75 ${h.link_to(_('Show full annotation anyway.'), h.url.current(fulldiff=1, **request.GET.mixed()))}
76 %else:
76 %else:
77 ${h.link_to(_('Show as raw.'), h.url('files_raw_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path))}
77 ${h.link_to(_('Show as raw.'), h.url('files_raw_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path))}
78 %endif
78 %endif
79 </h4>
79 </h4>
80 %endif
80 %endif
81 %endif
81 %endif
82 </div>
82 </div>
83 </div>
83 </div>
84
84
85 <script>
85 <script>
86 $(document).ready(function(){
86 $(document).ready(function(){
87 // fake html5 history state
87 // fake html5 history state
88 var _State = {
88 var _State = {
89 url: "${h.url.current()}",
89 url: "${h.url.current()}",
90 data: {
90 data: {
91 node_list_url: node_list_url.replace('__REV__',"${c.changeset.raw_id}").replace('__FPATH__', "${h.safe_unicode(c.file.path)}"),
91 node_list_url: node_list_url.replace('__REV__',"${c.changeset.raw_id}").replace('__FPATH__', "${h.safe_unicode(c.file.path)}"),
92 url_base: url_base.replace('__REV__',"${c.changeset.raw_id}"),
92 url_base: url_base.replace('__REV__',"${c.changeset.raw_id}"),
93 rev:"${c.changeset.raw_id}",
93 rev:"${c.changeset.raw_id}",
94 f_path: "${h.safe_unicode(c.file.path)}"
94 f_path: "${h.safe_unicode(c.file.path)}"
95 }
95 }
96 }
96 }
97 callbacks(_State); // defined in files.html, main callbacks. Triggered in pjax calls
97 callbacks(_State); // defined in files.html, main callbacks. Triggered in pjax calls
98 });
98 });
99 </script>
99 </script>
@@ -1,41 +1,40 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%block name="title">
4 <%block name="title">
5 ${_('%s Followers') % c.repo_name}
5 ${_('%s Followers') % c.repo_name}
6 </%block>
6 </%block>
7
7
8 <%def name="breadcrumbs_links()">
8 <%def name="breadcrumbs_links()">
9 ${_('Followers')}
9 ${_('Followers')}
10 </%def>
10 </%def>
11
11
12 <%block name="header_menu">
12 <%block name="header_menu">
13 ${self.menu('repositories')}
13 ${self.menu('repositories')}
14 </%block>
14 </%block>
15
15
16 <%def name="main()">
16 <%def name="main()">
17 ${self.repo_context_bar('followers')}
17 ${self.repo_context_bar('followers')}
18 <div class="panel panel-primary">
18 <div class="panel panel-primary">
19 <div class="panel-heading clearfix">
19 <div class="panel-heading clearfix">
20 ${self.breadcrumbs()}
20 ${self.breadcrumbs()}
21 </div>
21 </div>
22 <div class="panel-body">
22 <div class="panel-body">
23 <div id="followers">
23 <div id="followers">
24 <%include file='followers_data.html'/>
24 <%include file='followers_data.html'/>
25 </div>
25 </div>
26 </div>
26 </div>
27 </div>
27 </div>
28 <script type="text/javascript">
28 <script type="text/javascript">
29 $(document).ready(function(){
29 $(document).ready(function(){
30 var $followers = $('#followers');
30 var $followers = $('#followers');
31 $followers.on('click','.pager_link',function(e){
31 $followers.on('click','.pager_link',function(e){
32 asynchtml(e.target.href, $followers, function(){
32 asynchtml(e.target.href, $followers, function(){
33 show_more_event();
33 show_more_event();
34 tooltip_activate();
34 tooltip_activate();
35 show_changeset_tooltip();
36 });
35 });
37 e.preventDefault();
36 e.preventDefault();
38 });
37 });
39 });
38 });
40 </script>
39 </script>
41 </%def>
40 </%def>
@@ -1,41 +1,40 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%block name="title">
4 <%block name="title">
5 ${_('%s Forks') % c.repo_name}
5 ${_('%s Forks') % c.repo_name}
6 </%block>
6 </%block>
7
7
8 <%def name="breadcrumbs_links()">
8 <%def name="breadcrumbs_links()">
9 ${_('Forks')}
9 ${_('Forks')}
10 </%def>
10 </%def>
11
11
12 <%block name="header_menu">
12 <%block name="header_menu">
13 ${self.menu('repositories')}
13 ${self.menu('repositories')}
14 </%block>
14 </%block>
15
15
16 <%def name="main()">
16 <%def name="main()">
17 ${self.repo_context_bar('showforks')}
17 ${self.repo_context_bar('showforks')}
18 <div class="panel panel-primary">
18 <div class="panel panel-primary">
19 <div class="panel-heading clearfix">
19 <div class="panel-heading clearfix">
20 ${self.breadcrumbs()}
20 ${self.breadcrumbs()}
21 </div>
21 </div>
22 <div class="panel-body">
22 <div class="panel-body">
23 <div id="forks">
23 <div id="forks">
24 <%include file='forks_data.html'/>
24 <%include file='forks_data.html'/>
25 </div>
25 </div>
26 </div>
26 </div>
27 </div>
27 </div>
28 <script type="text/javascript">
28 <script type="text/javascript">
29 $(document).ready(function(){
29 $(document).ready(function(){
30 var $forks = $('#forks');
30 var $forks = $('#forks');
31 $forks.on('click','.pager_link',function(e){
31 $forks.on('click','.pager_link',function(e){
32 asynchtml(e.target.href, $forks, function(){
32 asynchtml(e.target.href, $forks, function(){
33 show_more_event();
33 show_more_event();
34 tooltip_activate();
34 tooltip_activate();
35 show_changeset_tooltip();
36 });
35 });
37 e.preventDefault();
36 e.preventDefault();
38 });
37 });
39 });
38 });
40 </script>
39 </script>
41 </%def>
40 </%def>
@@ -1,90 +1,88 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3 <%block name="title">
3 <%block name="title">
4 ${_('Journal')}
4 ${_('Journal')}
5 </%block>
5 </%block>
6 <%def name="breadcrumbs_links()">
6 <%def name="breadcrumbs_links()">
7 <form id="filter_form" class="pull-left form-inline">
7 <form id="filter_form" class="pull-left form-inline">
8 <input class="form-control q_filter_box ${'' if c.search_term else 'initial'}" id="j_filter" size="15" type="text" name="filter" value="${c.search_term or _('quick filter...')}"/>
8 <input class="form-control q_filter_box ${'' if c.search_term else 'initial'}" id="j_filter" size="15" type="text" name="filter" value="${c.search_term or _('quick filter...')}"/>
9 <span data-toggle="tooltip" title="${h.journal_filter_help()}">?</span>
9 <span data-toggle="tooltip" title="${h.journal_filter_help()}">?</span>
10 <input type='submit' value="${_('Filter')}" class="btn btn-default btn-xs"/>
10 <input type='submit' value="${_('Filter')}" class="btn btn-default btn-xs"/>
11 ${_('Journal')} - ${ungettext('%s Entry', '%s Entries', c.journal_pager.item_count) % (c.journal_pager.item_count)}
11 ${_('Journal')} - ${ungettext('%s Entry', '%s Entries', c.journal_pager.item_count) % (c.journal_pager.item_count)}
12 </form>
12 </form>
13 </%def>
13 </%def>
14 <%block name="header_menu">
14 <%block name="header_menu">
15 ${self.menu('journal')}
15 ${self.menu('journal')}
16 </%block>
16 </%block>
17 <%block name="head_extra">
17 <%block name="head_extra">
18 <link href="${h.url('journal_atom', api_key=c.authuser.api_key)}" rel="alternate" title="${_('ATOM journal feed')}" type="application/atom+xml" />
18 <link href="${h.url('journal_atom', api_key=c.authuser.api_key)}" rel="alternate" title="${_('ATOM journal feed')}" type="application/atom+xml" />
19 <link href="${h.url('journal_rss', api_key=c.authuser.api_key)}" rel="alternate" title="${_('RSS journal feed')}" type="application/rss+xml" />
19 <link href="${h.url('journal_rss', api_key=c.authuser.api_key)}" rel="alternate" title="${_('RSS journal feed')}" type="application/rss+xml" />
20 </%block>
20 </%block>
21
21
22 <%def name="main()">
22 <%def name="main()">
23 <div class="panel panel-primary">
23 <div class="panel panel-primary">
24 <div class="panel-heading clearfix">
24 <div class="panel-heading clearfix">
25 <div class="pull-left">
25 <div class="pull-left">
26 ${self.breadcrumbs()}
26 ${self.breadcrumbs()}
27 </div>
27 </div>
28 <div class="pull-right panel-title">
28 <div class="pull-right panel-title">
29 <a href="${h.url('my_account_watched')}"><i class="icon-eye"></i> ${_('Watched Repositories')}</a>
29 <a href="${h.url('my_account_watched')}"><i class="icon-eye"></i> ${_('Watched Repositories')}</a>
30 <a href="${h.url('my_account_repos')}"><i class="icon-database"></i> ${_('My Repositories')}</a>
30 <a href="${h.url('my_account_repos')}"><i class="icon-database"></i> ${_('My Repositories')}</a>
31 <a id="refresh" href="${h.url('journal')}"><i class="icon-arrows-cw"></i></a>
31 <a id="refresh" href="${h.url('journal')}"><i class="icon-arrows-cw"></i></a>
32 <a href="${h.url('journal_atom', api_key=c.authuser.api_key)}"><i class="icon-rss-squared"></i></a>
32 <a href="${h.url('journal_atom', api_key=c.authuser.api_key)}"><i class="icon-rss-squared"></i></a>
33 </div>
33 </div>
34 </div>
34 </div>
35 <div id="journal" class="panel-body">
35 <div id="journal" class="panel-body">
36 <%include file='journal_data.html'/>
36 <%include file='journal_data.html'/>
37 </div>
37 </div>
38 </div>
38 </div>
39
39
40 <script type="text/javascript">
40 <script type="text/javascript">
41
41
42 $('#j_filter').click(function(){
42 $('#j_filter').click(function(){
43 var $jfilter = $('#j_filter');
43 var $jfilter = $('#j_filter');
44 if($jfilter.hasClass('initial')){
44 if($jfilter.hasClass('initial')){
45 $jfilter.val('');
45 $jfilter.val('');
46 }
46 }
47 });
47 });
48 var fix_j_filter_width = function(len){
48 var fix_j_filter_width = function(len){
49 $('#j_filter').css('width', Math.max(80, len*6.50)+'px');
49 $('#j_filter').css('width', Math.max(80, len*6.50)+'px');
50 };
50 };
51 $('#j_filter').keyup(function(){
51 $('#j_filter').keyup(function(){
52 fix_j_filter_width($('#j_filter').val().length);
52 fix_j_filter_width($('#j_filter').val().length);
53 });
53 });
54 $('#filter_form').submit(function(e){
54 $('#filter_form').submit(function(e){
55 e.preventDefault();
55 e.preventDefault();
56 var val = $('#j_filter').val();
56 var val = $('#j_filter').val();
57 window.location = "${url.current(filter='__FILTER__')}".replace('__FILTER__',val);
57 window.location = "${url.current(filter='__FILTER__')}".replace('__FILTER__',val);
58 });
58 });
59 fix_j_filter_width($('#j_filter').val().length);
59 fix_j_filter_width($('#j_filter').val().length);
60
60
61 $('#refresh').click(function(e){
61 $('#refresh').click(function(e){
62 asynchtml("${h.url.current(filter=c.search_term)}", $("#journal"), function(){
62 asynchtml("${h.url.current(filter=c.search_term)}", $("#journal"), function(){
63 show_more_event();
63 show_more_event();
64 tooltip_activate();
64 tooltip_activate();
65 show_changeset_tooltip();
66 });
65 });
67 e.preventDefault();
66 e.preventDefault();
68 });
67 });
69
68
70 </script>
69 </script>
71
70
72 <script type="text/javascript">
71 <script type="text/javascript">
73 $(document).ready(function(){
72 $(document).ready(function(){
74 var $journal = $('#journal');
73 var $journal = $('#journal');
75 $journal.on('click','.pager_link',function(e){
74 $journal.on('click','.pager_link',function(e){
76 asynchtml(e.target.href, $journal, function(){
75 asynchtml(e.target.href, $journal, function(){
77 show_more_event();
76 show_more_event();
78 tooltip_activate();
77 tooltip_activate();
79 show_changeset_tooltip();
80 });
78 });
81 e.preventDefault();
79 e.preventDefault();
82 });
80 });
83 $('#journal').on('click','.show_more',function(e){
81 $('#journal').on('click','.show_more',function(e){
84 var el = e.target;
82 var el = e.target;
85 $('#'+el.id.substring(1)).show();
83 $('#'+el.id.substring(1)).show();
86 $(el.parentNode).hide();
84 $(el.parentNode).hide();
87 });
85 });
88 });
86 });
89 </script>
87 </script>
90 </%def>
88 </%def>
General Comments 0
You need to be logged in to leave comments. Login now