##// END OF EJS Templates
fixed few issues with autoselection of revisions on pull requests
marcink -
r2849:2b672f04 beta
parent child Browse files
Show More
@@ -1,415 +1,431 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.pullrequests
3 rhodecode.controllers.pullrequests
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 pull requests controller for rhodecode for initializing pull requests
6 pull requests controller for rhodecode for initializing pull requests
7
7
8 :created_on: May 7, 2012
8 :created_on: May 7, 2012
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 import logging
25 import logging
26 import traceback
26 import traceback
27 import formencode
27 import formencode
28
28
29 from webob.exc import HTTPNotFound, HTTPForbidden
29 from webob.exc import HTTPNotFound, HTTPForbidden
30 from collections import defaultdict
30 from collections import defaultdict
31 from itertools import groupby
31 from itertools import groupby
32
32
33 from pylons import request, response, session, tmpl_context as c, url
33 from pylons import request, response, session, tmpl_context as c, url
34 from pylons.controllers.util import abort, redirect
34 from pylons.controllers.util import abort, redirect
35 from pylons.i18n.translation import _
35 from pylons.i18n.translation import _
36 from pylons.decorators import jsonify
36 from pylons.decorators import jsonify
37
37
38 from rhodecode.lib.compat import json
38 from rhodecode.lib.compat import json
39 from rhodecode.lib.base import BaseRepoController, render
39 from rhodecode.lib.base import BaseRepoController, render
40 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator,\
40 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator,\
41 NotAnonymous
41 NotAnonymous
42 from rhodecode.lib import helpers as h
42 from rhodecode.lib import helpers as h
43 from rhodecode.lib import diffs
43 from rhodecode.lib import diffs
44 from rhodecode.lib.utils import action_logger
44 from rhodecode.lib.utils import action_logger
45 from rhodecode.model.db import User, PullRequest, ChangesetStatus,\
45 from rhodecode.model.db import User, PullRequest, ChangesetStatus,\
46 ChangesetComment
46 ChangesetComment
47 from rhodecode.model.pull_request import PullRequestModel
47 from rhodecode.model.pull_request import PullRequestModel
48 from rhodecode.model.meta import Session
48 from rhodecode.model.meta import Session
49 from rhodecode.model.repo import RepoModel
49 from rhodecode.model.repo import RepoModel
50 from rhodecode.model.comment import ChangesetCommentsModel
50 from rhodecode.model.comment import ChangesetCommentsModel
51 from rhodecode.model.changeset_status import ChangesetStatusModel
51 from rhodecode.model.changeset_status import ChangesetStatusModel
52 from rhodecode.model.forms import PullRequestForm
52 from rhodecode.model.forms import PullRequestForm
53
53
54 log = logging.getLogger(__name__)
54 log = logging.getLogger(__name__)
55
55
56
56
57 class PullrequestsController(BaseRepoController):
57 class PullrequestsController(BaseRepoController):
58
58
59 @LoginRequired()
59 @LoginRequired()
60 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
60 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
61 'repository.admin')
61 'repository.admin')
62 def __before__(self):
62 def __before__(self):
63 super(PullrequestsController, self).__before__()
63 super(PullrequestsController, self).__before__()
64 repo_model = RepoModel()
64 repo_model = RepoModel()
65 c.users_array = repo_model.get_users_js()
65 c.users_array = repo_model.get_users_js()
66 c.users_groups_array = repo_model.get_users_groups_js()
66 c.users_groups_array = repo_model.get_users_groups_js()
67
67
68 def _get_repo_refs(self, repo):
68 def _get_repo_refs(self, repo):
69 hist_l = []
69 hist_l = []
70
70
71 branches_group = ([('branch:%s:%s' % (k, v), k) for
71 branches_group = ([('branch:%s:%s' % (k, v), k) for
72 k, v in repo.branches.iteritems()], _("Branches"))
72 k, v in repo.branches.iteritems()], _("Branches"))
73 bookmarks_group = ([('book:%s:%s' % (k, v), k) for
73 bookmarks_group = ([('book:%s:%s' % (k, v), k) for
74 k, v in repo.bookmarks.iteritems()], _("Bookmarks"))
74 k, v in repo.bookmarks.iteritems()], _("Bookmarks"))
75 tags_group = ([('tag:%s:%s' % (k, v), k) for
75 tags_group = ([('tag:%s:%s' % (k, v), k) for
76 k, v in repo.tags.iteritems()], _("Tags"))
76 k, v in repo.tags.iteritems()], _("Tags"))
77
77
78 hist_l.append(bookmarks_group)
78 hist_l.append(bookmarks_group)
79 hist_l.append(branches_group)
79 hist_l.append(branches_group)
80 hist_l.append(tags_group)
80 hist_l.append(tags_group)
81
81
82 return hist_l
82 return hist_l
83
83
84 def _get_default_rev(self, repo):
85 """
86 Get's default revision to do compare on pull request
87
88 :param repo:
89 """
90 repo = repo.scm_instance
91 if 'default' in repo.branches:
92 return 'default'
93 else:
94 #if repo doesn't have default branch return first found
95 return repo.branches.keys()[0]
96
84 def show_all(self, repo_name):
97 def show_all(self, repo_name):
85 c.pull_requests = PullRequestModel().get_all(repo_name)
98 c.pull_requests = PullRequestModel().get_all(repo_name)
86 c.repo_name = repo_name
99 c.repo_name = repo_name
87 return render('/pullrequests/pullrequest_show_all.html')
100 return render('/pullrequests/pullrequest_show_all.html')
88
101
89 @NotAnonymous()
102 @NotAnonymous()
90 def index(self):
103 def index(self):
91 org_repo = c.rhodecode_db_repo
104 org_repo = c.rhodecode_db_repo
92
105
93 if org_repo.scm_instance.alias != 'hg':
106 if org_repo.scm_instance.alias != 'hg':
94 log.error('Review not available for GIT REPOS')
107 log.error('Review not available for GIT REPOS')
95 raise HTTPNotFound
108 raise HTTPNotFound
96
109
97 other_repos_info = {}
110 other_repos_info = {}
98
111
99 c.org_refs = self._get_repo_refs(c.rhodecode_repo)
112 c.org_refs = self._get_repo_refs(c.rhodecode_repo)
100 c.org_repos = []
113 c.org_repos = []
101 c.other_repos = []
114 c.other_repos = []
102 c.org_repos.append((org_repo.repo_name, '%s/%s' % (
115 c.org_repos.append((org_repo.repo_name, '%s/%s' % (
103 org_repo.user.username, c.repo_name))
116 org_repo.user.username, c.repo_name))
104 )
117 )
105
118
106 # add org repo to other so we can open pull request agains itself
119 # add org repo to other so we can open pull request agains itself
107 c.other_repos.extend(c.org_repos)
120 c.other_repos.extend(c.org_repos)
108
121
109 c.default_pull_request = org_repo.repo_name
122 c.default_pull_request = org_repo.repo_name # repo name pre-selected
123 c.default_pull_request_rev = self._get_default_rev(org_repo) # revision pre-selected
110 c.default_revs = self._get_repo_refs(org_repo.scm_instance)
124 c.default_revs = self._get_repo_refs(org_repo.scm_instance)
111 #add orginal repo
125 #add orginal repo
112 other_repos_info[org_repo.repo_name] = {
126 other_repos_info[org_repo.repo_name] = {
113 'gravatar': h.gravatar_url(org_repo.user.email, 24),
127 'gravatar': h.gravatar_url(org_repo.user.email, 24),
114 'description': org_repo.description,
128 'description': org_repo.description,
115 'revs': h.select('other_ref', '', c.default_revs, class_='refs')
129 'revs': h.select('other_ref', '', c.default_revs, class_='refs')
116 }
130 }
117
131
118 #gather forks and add to this list
132 #gather forks and add to this list
119 for fork in org_repo.forks:
133 for fork in org_repo.forks:
120 c.other_repos.append((fork.repo_name, '%s/%s' % (
134 c.other_repos.append((fork.repo_name, '%s/%s' % (
121 fork.user.username, fork.repo_name))
135 fork.user.username, fork.repo_name))
122 )
136 )
123 other_repos_info[fork.repo_name] = {
137 other_repos_info[fork.repo_name] = {
124 'gravatar': h.gravatar_url(fork.user.email, 24),
138 'gravatar': h.gravatar_url(fork.user.email, 24),
125 'description': fork.description,
139 'description': fork.description,
126 'revs': h.select('other_ref', '',
140 'revs': h.select('other_ref', '',
127 self._get_repo_refs(fork.scm_instance),
141 self._get_repo_refs(fork.scm_instance),
128 class_='refs')
142 class_='refs')
129 }
143 }
130 #add parents of this fork also
144 #add parents of this fork also
131 if org_repo.parent:
145 if org_repo.parent:
132 c.default_pull_request = org_repo.parent.repo_name
146 c.default_pull_request = org_repo.parent.repo_name
147 c.default_pull_request_rev = self._get_default_rev(org_repo.parent)
148 c.default_revs = self._get_repo_refs(org_repo.parent.scm_instance)
133 c.other_repos.append((org_repo.parent.repo_name, '%s/%s' % (
149 c.other_repos.append((org_repo.parent.repo_name, '%s/%s' % (
134 org_repo.parent.user.username,
150 org_repo.parent.user.username,
135 org_repo.parent.repo_name))
151 org_repo.parent.repo_name))
136 )
152 )
137 other_repos_info[org_repo.parent.repo_name] = {
153 other_repos_info[org_repo.parent.repo_name] = {
138 'gravatar': h.gravatar_url(org_repo.parent.user.email, 24),
154 'gravatar': h.gravatar_url(org_repo.parent.user.email, 24),
139 'description': org_repo.parent.description,
155 'description': org_repo.parent.description,
140 'revs': h.select('other_ref', '',
156 'revs': h.select('other_ref', '',
141 self._get_repo_refs(org_repo.parent.scm_instance),
157 self._get_repo_refs(org_repo.parent.scm_instance),
142 class_='refs')
158 class_='refs')
143 }
159 }
144
160
145 c.other_repos_info = json.dumps(other_repos_info)
161 c.other_repos_info = json.dumps(other_repos_info)
146 c.review_members = [org_repo.user]
162 c.review_members = [org_repo.user]
147 return render('/pullrequests/pullrequest.html')
163 return render('/pullrequests/pullrequest.html')
148
164
149 @NotAnonymous()
165 @NotAnonymous()
150 def create(self, repo_name):
166 def create(self, repo_name):
151 try:
167 try:
152 _form = PullRequestForm()().to_python(request.POST)
168 _form = PullRequestForm()().to_python(request.POST)
153 except formencode.Invalid, errors:
169 except formencode.Invalid, errors:
154 log.error(traceback.format_exc())
170 log.error(traceback.format_exc())
155 if errors.error_dict.get('revisions'):
171 if errors.error_dict.get('revisions'):
156 msg = 'Revisions: %s' % errors.error_dict['revisions']
172 msg = 'Revisions: %s' % errors.error_dict['revisions']
157 elif errors.error_dict.get('pullrequest_title'):
173 elif errors.error_dict.get('pullrequest_title'):
158 msg = _('Pull request requires a title with min. 3 chars')
174 msg = _('Pull request requires a title with min. 3 chars')
159 else:
175 else:
160 msg = _('error during creation of pull request')
176 msg = _('error during creation of pull request')
161
177
162 h.flash(msg, 'error')
178 h.flash(msg, 'error')
163 return redirect(url('pullrequest_home', repo_name=repo_name))
179 return redirect(url('pullrequest_home', repo_name=repo_name))
164
180
165 org_repo = _form['org_repo']
181 org_repo = _form['org_repo']
166 org_ref = _form['org_ref']
182 org_ref = _form['org_ref']
167 other_repo = _form['other_repo']
183 other_repo = _form['other_repo']
168 other_ref = _form['other_ref']
184 other_ref = _form['other_ref']
169 revisions = _form['revisions']
185 revisions = _form['revisions']
170 reviewers = _form['review_members']
186 reviewers = _form['review_members']
171
187
172 title = _form['pullrequest_title']
188 title = _form['pullrequest_title']
173 description = _form['pullrequest_desc']
189 description = _form['pullrequest_desc']
174
190
175 try:
191 try:
176 pull_request = PullRequestModel().create(
192 pull_request = PullRequestModel().create(
177 self.rhodecode_user.user_id, org_repo, org_ref, other_repo,
193 self.rhodecode_user.user_id, org_repo, org_ref, other_repo,
178 other_ref, revisions, reviewers, title, description
194 other_ref, revisions, reviewers, title, description
179 )
195 )
180 Session().commit()
196 Session().commit()
181 h.flash(_('Successfully opened new pull request'),
197 h.flash(_('Successfully opened new pull request'),
182 category='success')
198 category='success')
183 except Exception:
199 except Exception:
184 h.flash(_('Error occurred during sending pull request'),
200 h.flash(_('Error occurred during sending pull request'),
185 category='error')
201 category='error')
186 log.error(traceback.format_exc())
202 log.error(traceback.format_exc())
187 return redirect(url('pullrequest_home', repo_name=repo_name))
203 return redirect(url('pullrequest_home', repo_name=repo_name))
188
204
189 return redirect(url('pullrequest_show', repo_name=other_repo,
205 return redirect(url('pullrequest_show', repo_name=other_repo,
190 pull_request_id=pull_request.pull_request_id))
206 pull_request_id=pull_request.pull_request_id))
191
207
192 @NotAnonymous()
208 @NotAnonymous()
193 @jsonify
209 @jsonify
194 def update(self, repo_name, pull_request_id):
210 def update(self, repo_name, pull_request_id):
195 pull_request = PullRequest.get_or_404(pull_request_id)
211 pull_request = PullRequest.get_or_404(pull_request_id)
196 if pull_request.is_closed():
212 if pull_request.is_closed():
197 raise HTTPForbidden()
213 raise HTTPForbidden()
198 #only owner or admin can update it
214 #only owner or admin can update it
199 owner = pull_request.author.user_id == c.rhodecode_user.user_id
215 owner = pull_request.author.user_id == c.rhodecode_user.user_id
200 if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner:
216 if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner:
201 reviewers_ids = map(int, filter(lambda v: v not in [None, ''],
217 reviewers_ids = map(int, filter(lambda v: v not in [None, ''],
202 request.POST.get('reviewers_ids', '').split(',')))
218 request.POST.get('reviewers_ids', '').split(',')))
203
219
204 PullRequestModel().update_reviewers(pull_request_id, reviewers_ids)
220 PullRequestModel().update_reviewers(pull_request_id, reviewers_ids)
205 Session.commit()
221 Session.commit()
206 return True
222 return True
207 raise HTTPForbidden()
223 raise HTTPForbidden()
208
224
209 @NotAnonymous()
225 @NotAnonymous()
210 @jsonify
226 @jsonify
211 def delete(self, repo_name, pull_request_id):
227 def delete(self, repo_name, pull_request_id):
212 pull_request = PullRequest.get_or_404(pull_request_id)
228 pull_request = PullRequest.get_or_404(pull_request_id)
213 #only owner can delete it !
229 #only owner can delete it !
214 if pull_request.author.user_id == c.rhodecode_user.user_id:
230 if pull_request.author.user_id == c.rhodecode_user.user_id:
215 PullRequestModel().delete(pull_request)
231 PullRequestModel().delete(pull_request)
216 Session().commit()
232 Session().commit()
217 h.flash(_('Successfully deleted pull request'),
233 h.flash(_('Successfully deleted pull request'),
218 category='success')
234 category='success')
219 return redirect(url('admin_settings_my_account'))
235 return redirect(url('admin_settings_my_account'))
220 raise HTTPForbidden()
236 raise HTTPForbidden()
221
237
222 def _load_compare_data(self, pull_request, enable_comments=True):
238 def _load_compare_data(self, pull_request, enable_comments=True):
223 """
239 """
224 Load context data needed for generating compare diff
240 Load context data needed for generating compare diff
225
241
226 :param pull_request:
242 :param pull_request:
227 :type pull_request:
243 :type pull_request:
228 """
244 """
229
245
230 org_repo = pull_request.org_repo
246 org_repo = pull_request.org_repo
231 (org_ref_type,
247 (org_ref_type,
232 org_ref_name,
248 org_ref_name,
233 org_ref_rev) = pull_request.org_ref.split(':')
249 org_ref_rev) = pull_request.org_ref.split(':')
234
250
235 other_repo = pull_request.other_repo
251 other_repo = pull_request.other_repo
236 (other_ref_type,
252 (other_ref_type,
237 other_ref_name,
253 other_ref_name,
238 other_ref_rev) = pull_request.other_ref.split(':')
254 other_ref_rev) = pull_request.other_ref.split(':')
239
255
240 # despite opening revisions for bookmarks/branches/tags, we always
256 # despite opening revisions for bookmarks/branches/tags, we always
241 # convert this to rev to prevent changes after book or branch change
257 # convert this to rev to prevent changes after book or branch change
242 org_ref = ('rev', org_ref_rev)
258 org_ref = ('rev', org_ref_rev)
243 other_ref = ('rev', other_ref_rev)
259 other_ref = ('rev', other_ref_rev)
244
260
245 c.org_repo = org_repo
261 c.org_repo = org_repo
246 c.other_repo = other_repo
262 c.other_repo = other_repo
247
263
248 c.cs_ranges, discovery_data = PullRequestModel().get_compare_data(
264 c.cs_ranges, discovery_data = PullRequestModel().get_compare_data(
249 org_repo, org_ref, other_repo, other_ref
265 org_repo, org_ref, other_repo, other_ref
250 )
266 )
251
267
252 c.statuses = org_repo.statuses([x.raw_id for x in c.cs_ranges])
268 c.statuses = org_repo.statuses([x.raw_id for x in c.cs_ranges])
253 # defines that we need hidden inputs with changesets
269 # defines that we need hidden inputs with changesets
254 c.as_form = request.GET.get('as_form', False)
270 c.as_form = request.GET.get('as_form', False)
255
271
256 c.org_ref = org_ref[1]
272 c.org_ref = org_ref[1]
257 c.other_ref = other_ref[1]
273 c.other_ref = other_ref[1]
258 # diff needs to have swapped org with other to generate proper diff
274 # diff needs to have swapped org with other to generate proper diff
259 _diff = diffs.differ(other_repo, other_ref, org_repo, org_ref,
275 _diff = diffs.differ(other_repo, other_ref, org_repo, org_ref,
260 discovery_data)
276 discovery_data)
261 diff_processor = diffs.DiffProcessor(_diff, format='gitdiff')
277 diff_processor = diffs.DiffProcessor(_diff, format='gitdiff')
262 _parsed = diff_processor.prepare()
278 _parsed = diff_processor.prepare()
263
279
264 c.files = []
280 c.files = []
265 c.changes = {}
281 c.changes = {}
266
282
267 for f in _parsed:
283 for f in _parsed:
268 fid = h.FID('', f['filename'])
284 fid = h.FID('', f['filename'])
269 c.files.append([fid, f['operation'], f['filename'], f['stats']])
285 c.files.append([fid, f['operation'], f['filename'], f['stats']])
270 diff = diff_processor.as_html(enable_comments=enable_comments,
286 diff = diff_processor.as_html(enable_comments=enable_comments,
271 diff_lines=[f])
287 diff_lines=[f])
272 c.changes[fid] = [f['operation'], f['filename'], diff]
288 c.changes[fid] = [f['operation'], f['filename'], diff]
273
289
274 def show(self, repo_name, pull_request_id):
290 def show(self, repo_name, pull_request_id):
275 repo_model = RepoModel()
291 repo_model = RepoModel()
276 c.users_array = repo_model.get_users_js()
292 c.users_array = repo_model.get_users_js()
277 c.users_groups_array = repo_model.get_users_groups_js()
293 c.users_groups_array = repo_model.get_users_groups_js()
278 c.pull_request = PullRequest.get_or_404(pull_request_id)
294 c.pull_request = PullRequest.get_or_404(pull_request_id)
279 c.target_repo = c.pull_request.org_repo.repo_name
295 c.target_repo = c.pull_request.org_repo.repo_name
280
296
281 cc_model = ChangesetCommentsModel()
297 cc_model = ChangesetCommentsModel()
282 cs_model = ChangesetStatusModel()
298 cs_model = ChangesetStatusModel()
283 _cs_statuses = cs_model.get_statuses(c.pull_request.org_repo,
299 _cs_statuses = cs_model.get_statuses(c.pull_request.org_repo,
284 pull_request=c.pull_request,
300 pull_request=c.pull_request,
285 with_revisions=True)
301 with_revisions=True)
286
302
287 cs_statuses = defaultdict(list)
303 cs_statuses = defaultdict(list)
288 for st in _cs_statuses:
304 for st in _cs_statuses:
289 cs_statuses[st.author.username] += [st]
305 cs_statuses[st.author.username] += [st]
290
306
291 c.pull_request_reviewers = []
307 c.pull_request_reviewers = []
292 c.pull_request_pending_reviewers = []
308 c.pull_request_pending_reviewers = []
293 for o in c.pull_request.reviewers:
309 for o in c.pull_request.reviewers:
294 st = cs_statuses.get(o.user.username, None)
310 st = cs_statuses.get(o.user.username, None)
295 if st:
311 if st:
296 sorter = lambda k: k.version
312 sorter = lambda k: k.version
297 st = [(x, list(y)[0])
313 st = [(x, list(y)[0])
298 for x, y in (groupby(sorted(st, key=sorter), sorter))]
314 for x, y in (groupby(sorted(st, key=sorter), sorter))]
299 else:
315 else:
300 c.pull_request_pending_reviewers.append(o.user)
316 c.pull_request_pending_reviewers.append(o.user)
301 c.pull_request_reviewers.append([o.user, st])
317 c.pull_request_reviewers.append([o.user, st])
302
318
303 # pull_requests repo_name we opened it against
319 # pull_requests repo_name we opened it against
304 # ie. other_repo must match
320 # ie. other_repo must match
305 if repo_name != c.pull_request.other_repo.repo_name:
321 if repo_name != c.pull_request.other_repo.repo_name:
306 raise HTTPNotFound
322 raise HTTPNotFound
307
323
308 # load compare data into template context
324 # load compare data into template context
309 enable_comments = not c.pull_request.is_closed()
325 enable_comments = not c.pull_request.is_closed()
310 self._load_compare_data(c.pull_request, enable_comments=enable_comments)
326 self._load_compare_data(c.pull_request, enable_comments=enable_comments)
311
327
312 # inline comments
328 # inline comments
313 c.inline_cnt = 0
329 c.inline_cnt = 0
314 c.inline_comments = cc_model.get_inline_comments(
330 c.inline_comments = cc_model.get_inline_comments(
315 c.rhodecode_db_repo.repo_id,
331 c.rhodecode_db_repo.repo_id,
316 pull_request=pull_request_id)
332 pull_request=pull_request_id)
317 # count inline comments
333 # count inline comments
318 for __, lines in c.inline_comments:
334 for __, lines in c.inline_comments:
319 for comments in lines.values():
335 for comments in lines.values():
320 c.inline_cnt += len(comments)
336 c.inline_cnt += len(comments)
321 # comments
337 # comments
322 c.comments = cc_model.get_comments(c.rhodecode_db_repo.repo_id,
338 c.comments = cc_model.get_comments(c.rhodecode_db_repo.repo_id,
323 pull_request=pull_request_id)
339 pull_request=pull_request_id)
324
340
325 try:
341 try:
326 cur_status = c.statuses[c.pull_request.revisions[0]][0]
342 cur_status = c.statuses[c.pull_request.revisions[0]][0]
327 except:
343 except:
328 log.error(traceback.format_exc())
344 log.error(traceback.format_exc())
329 cur_status = 'undefined'
345 cur_status = 'undefined'
330 if c.pull_request.is_closed() and 0:
346 if c.pull_request.is_closed() and 0:
331 c.current_changeset_status = cur_status
347 c.current_changeset_status = cur_status
332 else:
348 else:
333 # changeset(pull-request) status calulation based on reviewers
349 # changeset(pull-request) status calulation based on reviewers
334 c.current_changeset_status = cs_model.calculate_status(
350 c.current_changeset_status = cs_model.calculate_status(
335 c.pull_request_reviewers,
351 c.pull_request_reviewers,
336 )
352 )
337 c.changeset_statuses = ChangesetStatus.STATUSES
353 c.changeset_statuses = ChangesetStatus.STATUSES
338
354
339 return render('/pullrequests/pullrequest_show.html')
355 return render('/pullrequests/pullrequest_show.html')
340
356
341 @NotAnonymous()
357 @NotAnonymous()
342 @jsonify
358 @jsonify
343 def comment(self, repo_name, pull_request_id):
359 def comment(self, repo_name, pull_request_id):
344 pull_request = PullRequest.get_or_404(pull_request_id)
360 pull_request = PullRequest.get_or_404(pull_request_id)
345 if pull_request.is_closed():
361 if pull_request.is_closed():
346 raise HTTPForbidden()
362 raise HTTPForbidden()
347
363
348 status = request.POST.get('changeset_status')
364 status = request.POST.get('changeset_status')
349 change_status = request.POST.get('change_changeset_status')
365 change_status = request.POST.get('change_changeset_status')
350 text = request.POST.get('text')
366 text = request.POST.get('text')
351 if status and change_status:
367 if status and change_status:
352 text = text or (_('Status change -> %s')
368 text = text or (_('Status change -> %s')
353 % ChangesetStatus.get_status_lbl(status))
369 % ChangesetStatus.get_status_lbl(status))
354 comm = ChangesetCommentsModel().create(
370 comm = ChangesetCommentsModel().create(
355 text=text,
371 text=text,
356 repo=c.rhodecode_db_repo.repo_id,
372 repo=c.rhodecode_db_repo.repo_id,
357 user=c.rhodecode_user.user_id,
373 user=c.rhodecode_user.user_id,
358 pull_request=pull_request_id,
374 pull_request=pull_request_id,
359 f_path=request.POST.get('f_path'),
375 f_path=request.POST.get('f_path'),
360 line_no=request.POST.get('line'),
376 line_no=request.POST.get('line'),
361 status_change=(ChangesetStatus.get_status_lbl(status)
377 status_change=(ChangesetStatus.get_status_lbl(status)
362 if status and change_status else None)
378 if status and change_status else None)
363 )
379 )
364
380
365 # get status if set !
381 # get status if set !
366 if status and change_status:
382 if status and change_status:
367 ChangesetStatusModel().set_status(
383 ChangesetStatusModel().set_status(
368 c.rhodecode_db_repo.repo_id,
384 c.rhodecode_db_repo.repo_id,
369 status,
385 status,
370 c.rhodecode_user.user_id,
386 c.rhodecode_user.user_id,
371 comm,
387 comm,
372 pull_request=pull_request_id
388 pull_request=pull_request_id
373 )
389 )
374 action_logger(self.rhodecode_user,
390 action_logger(self.rhodecode_user,
375 'user_commented_pull_request:%s' % pull_request_id,
391 'user_commented_pull_request:%s' % pull_request_id,
376 c.rhodecode_db_repo, self.ip_addr, self.sa)
392 c.rhodecode_db_repo, self.ip_addr, self.sa)
377
393
378 if request.POST.get('save_close'):
394 if request.POST.get('save_close'):
379 PullRequestModel().close_pull_request(pull_request_id)
395 PullRequestModel().close_pull_request(pull_request_id)
380 action_logger(self.rhodecode_user,
396 action_logger(self.rhodecode_user,
381 'user_closed_pull_request:%s' % pull_request_id,
397 'user_closed_pull_request:%s' % pull_request_id,
382 c.rhodecode_db_repo, self.ip_addr, self.sa)
398 c.rhodecode_db_repo, self.ip_addr, self.sa)
383
399
384 Session().commit()
400 Session().commit()
385
401
386 if not request.environ.get('HTTP_X_PARTIAL_XHR'):
402 if not request.environ.get('HTTP_X_PARTIAL_XHR'):
387 return redirect(h.url('pullrequest_show', repo_name=repo_name,
403 return redirect(h.url('pullrequest_show', repo_name=repo_name,
388 pull_request_id=pull_request_id))
404 pull_request_id=pull_request_id))
389
405
390 data = {
406 data = {
391 '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'))),
392 }
408 }
393 if comm:
409 if comm:
394 c.co = comm
410 c.co = comm
395 data.update(comm.get_dict())
411 data.update(comm.get_dict())
396 data.update({'rendered_text':
412 data.update({'rendered_text':
397 render('changeset/changeset_comment_block.html')})
413 render('changeset/changeset_comment_block.html')})
398
414
399 return data
415 return data
400
416
401 @NotAnonymous()
417 @NotAnonymous()
402 @jsonify
418 @jsonify
403 def delete_comment(self, repo_name, comment_id):
419 def delete_comment(self, repo_name, comment_id):
404 co = ChangesetComment.get(comment_id)
420 co = ChangesetComment.get(comment_id)
405 if co.pull_request.is_closed():
421 if co.pull_request.is_closed():
406 #don't allow deleting comments on closed pull request
422 #don't allow deleting comments on closed pull request
407 raise HTTPForbidden()
423 raise HTTPForbidden()
408
424
409 owner = lambda: co.author.user_id == c.rhodecode_user.user_id
425 owner = lambda: co.author.user_id == c.rhodecode_user.user_id
410 if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner:
426 if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner:
411 ChangesetCommentsModel().delete(comment=co)
427 ChangesetCommentsModel().delete(comment=co)
412 Session().commit()
428 Session().commit()
413 return True
429 return True
414 else:
430 else:
415 raise HTTPForbidden()
431 raise HTTPForbidden()
@@ -1,1757 +1,1768 b''
1 /**
1 /**
2 RhodeCode JS Files
2 RhodeCode JS Files
3 **/
3 **/
4
4
5 if (typeof console == "undefined" || typeof console.log == "undefined"){
5 if (typeof console == "undefined" || typeof console.log == "undefined"){
6 console = { log: function() {} }
6 console = { log: function() {} }
7 }
7 }
8
8
9
9
10 var str_repeat = function(i, m) {
10 var str_repeat = function(i, m) {
11 for (var o = []; m > 0; o[--m] = i);
11 for (var o = []; m > 0; o[--m] = i);
12 return o.join('');
12 return o.join('');
13 };
13 };
14
14
15 /**
15 /**
16 * INJECT .format function into String
16 * INJECT .format function into String
17 * Usage: "My name is {0} {1}".format("Johny","Bravo")
17 * Usage: "My name is {0} {1}".format("Johny","Bravo")
18 * Return "My name is Johny Bravo"
18 * Return "My name is Johny Bravo"
19 * Inspired by https://gist.github.com/1049426
19 * Inspired by https://gist.github.com/1049426
20 */
20 */
21 String.prototype.format = function() {
21 String.prototype.format = function() {
22
22
23 function format() {
23 function format() {
24 var str = this;
24 var str = this;
25 var len = arguments.length+1;
25 var len = arguments.length+1;
26 var safe = undefined;
26 var safe = undefined;
27 var arg = undefined;
27 var arg = undefined;
28
28
29 // For each {0} {1} {n...} replace with the argument in that position. If
29 // For each {0} {1} {n...} replace with the argument in that position. If
30 // the argument is an object or an array it will be stringified to JSON.
30 // the argument is an object or an array it will be stringified to JSON.
31 for (var i=0; i < len; arg = arguments[i++]) {
31 for (var i=0; i < len; arg = arguments[i++]) {
32 safe = typeof arg === 'object' ? JSON.stringify(arg) : arg;
32 safe = typeof arg === 'object' ? JSON.stringify(arg) : arg;
33 str = str.replace(RegExp('\\{'+(i-1)+'\\}', 'g'), safe);
33 str = str.replace(RegExp('\\{'+(i-1)+'\\}', 'g'), safe);
34 }
34 }
35 return str;
35 return str;
36 }
36 }
37
37
38 // Save a reference of what may already exist under the property native.
38 // Save a reference of what may already exist under the property native.
39 // Allows for doing something like: if("".format.native) { /* use native */ }
39 // Allows for doing something like: if("".format.native) { /* use native */ }
40 format.native = String.prototype.format;
40 format.native = String.prototype.format;
41
41
42 // Replace the prototype property
42 // Replace the prototype property
43 return format;
43 return format;
44
44
45 }();
45 }();
46
46
47 String.prototype.strip = function(char) {
47 String.prototype.strip = function(char) {
48 if(char === undefined){
48 if(char === undefined){
49 char = '\\s';
49 char = '\\s';
50 }
50 }
51 return this.replace(new RegExp('^'+char+'+|'+char+'+$','g'), '');
51 return this.replace(new RegExp('^'+char+'+|'+char+'+$','g'), '');
52 }
52 }
53 String.prototype.lstrip = function(char) {
53 String.prototype.lstrip = function(char) {
54 if(char === undefined){
54 if(char === undefined){
55 char = '\\s';
55 char = '\\s';
56 }
56 }
57 return this.replace(new RegExp('^'+char+'+'),'');
57 return this.replace(new RegExp('^'+char+'+'),'');
58 }
58 }
59 String.prototype.rstrip = function(char) {
59 String.prototype.rstrip = function(char) {
60 if(char === undefined){
60 if(char === undefined){
61 char = '\\s';
61 char = '\\s';
62 }
62 }
63 return this.replace(new RegExp(''+char+'+$'),'');
63 return this.replace(new RegExp(''+char+'+$'),'');
64 }
64 }
65
65
66
66
67 if(!Array.prototype.indexOf) {
67 if(!Array.prototype.indexOf) {
68 Array.prototype.indexOf = function(needle) {
68 Array.prototype.indexOf = function(needle) {
69 for(var i = 0; i < this.length; i++) {
69 for(var i = 0; i < this.length; i++) {
70 if(this[i] === needle) {
70 if(this[i] === needle) {
71 return i;
71 return i;
72 }
72 }
73 }
73 }
74 return -1;
74 return -1;
75 };
75 };
76 }
76 }
77
77
78 // IE(CRAP) doesn't support previousElementSibling
78 // IE(CRAP) doesn't support previousElementSibling
79 var prevElementSibling = function( el ) {
79 var prevElementSibling = function( el ) {
80 if( el.previousElementSibling ) {
80 if( el.previousElementSibling ) {
81 return el.previousElementSibling;
81 return el.previousElementSibling;
82 } else {
82 } else {
83 while( el = el.previousSibling ) {
83 while( el = el.previousSibling ) {
84 if( el.nodeType === 1 ) return el;
84 if( el.nodeType === 1 ) return el;
85 }
85 }
86 }
86 }
87 }
87 }
88
88
89 var setSelectValue = function(select, val){
90 var selection = YUD.get(select);
89
91
92 // select element
93 for(var i=0;i<selection.options.length;i++){
94 console.log(selection.options[i].innerHTML);
95 if (selection.options[i].innerHTML == val) {
96 selection.selectedIndex = i;
97 break;
98 }
99 }
100 }
90
101
91
102
92 /**
103 /**
93 * SmartColorGenerator
104 * SmartColorGenerator
94 *
105 *
95 *usage::
106 *usage::
96 * var CG = new ColorGenerator();
107 * var CG = new ColorGenerator();
97 * var col = CG.getColor(key); //returns array of RGB
108 * var col = CG.getColor(key); //returns array of RGB
98 * 'rgb({0})'.format(col.join(',')
109 * 'rgb({0})'.format(col.join(',')
99 *
110 *
100 * @returns {ColorGenerator}
111 * @returns {ColorGenerator}
101 */
112 */
102 var ColorGenerator = function(){
113 var ColorGenerator = function(){
103 this.GOLDEN_RATIO = 0.618033988749895;
114 this.GOLDEN_RATIO = 0.618033988749895;
104 this.CURRENT_RATIO = 0.22717784590367374 // this can be random
115 this.CURRENT_RATIO = 0.22717784590367374 // this can be random
105 this.HSV_1 = 0.75;//saturation
116 this.HSV_1 = 0.75;//saturation
106 this.HSV_2 = 0.95;
117 this.HSV_2 = 0.95;
107 this.color;
118 this.color;
108 this.cacheColorMap = {};
119 this.cacheColorMap = {};
109 };
120 };
110
121
111 ColorGenerator.prototype = {
122 ColorGenerator.prototype = {
112 getColor:function(key){
123 getColor:function(key){
113 if(this.cacheColorMap[key] !== undefined){
124 if(this.cacheColorMap[key] !== undefined){
114 return this.cacheColorMap[key];
125 return this.cacheColorMap[key];
115 }
126 }
116 else{
127 else{
117 this.cacheColorMap[key] = this.generateColor();
128 this.cacheColorMap[key] = this.generateColor();
118 return this.cacheColorMap[key];
129 return this.cacheColorMap[key];
119 }
130 }
120 },
131 },
121 _hsvToRgb:function(h,s,v){
132 _hsvToRgb:function(h,s,v){
122 if (s == 0.0)
133 if (s == 0.0)
123 return [v, v, v];
134 return [v, v, v];
124 i = parseInt(h * 6.0)
135 i = parseInt(h * 6.0)
125 f = (h * 6.0) - i
136 f = (h * 6.0) - i
126 p = v * (1.0 - s)
137 p = v * (1.0 - s)
127 q = v * (1.0 - s * f)
138 q = v * (1.0 - s * f)
128 t = v * (1.0 - s * (1.0 - f))
139 t = v * (1.0 - s * (1.0 - f))
129 i = i % 6
140 i = i % 6
130 if (i == 0)
141 if (i == 0)
131 return [v, t, p]
142 return [v, t, p]
132 if (i == 1)
143 if (i == 1)
133 return [q, v, p]
144 return [q, v, p]
134 if (i == 2)
145 if (i == 2)
135 return [p, v, t]
146 return [p, v, t]
136 if (i == 3)
147 if (i == 3)
137 return [p, q, v]
148 return [p, q, v]
138 if (i == 4)
149 if (i == 4)
139 return [t, p, v]
150 return [t, p, v]
140 if (i == 5)
151 if (i == 5)
141 return [v, p, q]
152 return [v, p, q]
142 },
153 },
143 generateColor:function(){
154 generateColor:function(){
144 this.CURRENT_RATIO = this.CURRENT_RATIO+this.GOLDEN_RATIO;
155 this.CURRENT_RATIO = this.CURRENT_RATIO+this.GOLDEN_RATIO;
145 this.CURRENT_RATIO = this.CURRENT_RATIO %= 1;
156 this.CURRENT_RATIO = this.CURRENT_RATIO %= 1;
146 HSV_tuple = [this.CURRENT_RATIO, this.HSV_1, this.HSV_2]
157 HSV_tuple = [this.CURRENT_RATIO, this.HSV_1, this.HSV_2]
147 RGB_tuple = this._hsvToRgb(HSV_tuple[0],HSV_tuple[1],HSV_tuple[2]);
158 RGB_tuple = this._hsvToRgb(HSV_tuple[0],HSV_tuple[1],HSV_tuple[2]);
148 function toRgb(v){
159 function toRgb(v){
149 return ""+parseInt(v*256)
160 return ""+parseInt(v*256)
150 }
161 }
151 return [toRgb(RGB_tuple[0]),toRgb(RGB_tuple[1]),toRgb(RGB_tuple[2])];
162 return [toRgb(RGB_tuple[0]),toRgb(RGB_tuple[1]),toRgb(RGB_tuple[2])];
152
163
153 }
164 }
154 }
165 }
155
166
156
167
157
168
158
169
159
170
160 /**
171 /**
161 * GLOBAL YUI Shortcuts
172 * GLOBAL YUI Shortcuts
162 */
173 */
163 var YUC = YAHOO.util.Connect;
174 var YUC = YAHOO.util.Connect;
164 var YUD = YAHOO.util.Dom;
175 var YUD = YAHOO.util.Dom;
165 var YUE = YAHOO.util.Event;
176 var YUE = YAHOO.util.Event;
166 var YUQ = YAHOO.util.Selector.query;
177 var YUQ = YAHOO.util.Selector.query;
167
178
168 // defines if push state is enabled for this browser ?
179 // defines if push state is enabled for this browser ?
169 var push_state_enabled = Boolean(
180 var push_state_enabled = Boolean(
170 window.history && window.history.pushState && window.history.replaceState
181 window.history && window.history.pushState && window.history.replaceState
171 && !( /* disable for versions of iOS before version 4.3 (8F190) */
182 && !( /* disable for versions of iOS before version 4.3 (8F190) */
172 (/ Mobile\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i).test(navigator.userAgent)
183 (/ Mobile\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i).test(navigator.userAgent)
173 /* disable for the mercury iOS browser, or at least older versions of the webkit engine */
184 /* disable for the mercury iOS browser, or at least older versions of the webkit engine */
174 || (/AppleWebKit\/5([0-2]|3[0-2])/i).test(navigator.userAgent)
185 || (/AppleWebKit\/5([0-2]|3[0-2])/i).test(navigator.userAgent)
175 )
186 )
176 );
187 );
177
188
178 var _run_callbacks = function(callbacks){
189 var _run_callbacks = function(callbacks){
179 if (callbacks !== undefined){
190 if (callbacks !== undefined){
180 var _l = callbacks.length;
191 var _l = callbacks.length;
181 for (var i=0;i<_l;i++){
192 for (var i=0;i<_l;i++){
182 var func = callbacks[i];
193 var func = callbacks[i];
183 if(typeof(func)=='function'){
194 if(typeof(func)=='function'){
184 try{
195 try{
185 func();
196 func();
186 }catch (err){};
197 }catch (err){};
187 }
198 }
188 }
199 }
189 }
200 }
190 }
201 }
191
202
192 /**
203 /**
193 * Partial Ajax Implementation
204 * Partial Ajax Implementation
194 *
205 *
195 * @param url: defines url to make partial request
206 * @param url: defines url to make partial request
196 * @param container: defines id of container to input partial result
207 * @param container: defines id of container to input partial result
197 * @param s_call: success callback function that takes o as arg
208 * @param s_call: success callback function that takes o as arg
198 * o.tId
209 * o.tId
199 * o.status
210 * o.status
200 * o.statusText
211 * o.statusText
201 * o.getResponseHeader[ ]
212 * o.getResponseHeader[ ]
202 * o.getAllResponseHeaders
213 * o.getAllResponseHeaders
203 * o.responseText
214 * o.responseText
204 * o.responseXML
215 * o.responseXML
205 * o.argument
216 * o.argument
206 * @param f_call: failure callback
217 * @param f_call: failure callback
207 * @param args arguments
218 * @param args arguments
208 */
219 */
209 function ypjax(url,container,s_call,f_call,args){
220 function ypjax(url,container,s_call,f_call,args){
210 var method='GET';
221 var method='GET';
211 if(args===undefined){
222 if(args===undefined){
212 args=null;
223 args=null;
213 }
224 }
214
225
215 // Set special header for partial ajax == HTTP_X_PARTIAL_XHR
226 // Set special header for partial ajax == HTTP_X_PARTIAL_XHR
216 YUC.initHeader('X-PARTIAL-XHR',true);
227 YUC.initHeader('X-PARTIAL-XHR',true);
217
228
218 // wrapper of passed callback
229 // wrapper of passed callback
219 var s_wrapper = (function(o){
230 var s_wrapper = (function(o){
220 return function(o){
231 return function(o){
221 YUD.get(container).innerHTML=o.responseText;
232 YUD.get(container).innerHTML=o.responseText;
222 YUD.setStyle(container,'opacity','1.0');
233 YUD.setStyle(container,'opacity','1.0');
223 //execute the given original callback
234 //execute the given original callback
224 if (s_call !== undefined){
235 if (s_call !== undefined){
225 s_call(o);
236 s_call(o);
226 }
237 }
227 }
238 }
228 })()
239 })()
229 YUD.setStyle(container,'opacity','0.3');
240 YUD.setStyle(container,'opacity','0.3');
230 YUC.asyncRequest(method,url,{
241 YUC.asyncRequest(method,url,{
231 success:s_wrapper,
242 success:s_wrapper,
232 failure:function(o){
243 failure:function(o){
233 console.log(o);
244 console.log(o);
234 YUD.get(container).innerHTML='<span class="error_red">ERROR: {0}</span>'.format(o.status);
245 YUD.get(container).innerHTML='<span class="error_red">ERROR: {0}</span>'.format(o.status);
235 YUD.setStyle(container,'opacity','1.0');
246 YUD.setStyle(container,'opacity','1.0');
236 },
247 },
237 cache:false
248 cache:false
238 },args);
249 },args);
239
250
240 };
251 };
241
252
242 var ajaxPOST = function(url,postData,success) {
253 var ajaxPOST = function(url,postData,success) {
243 // Set special header for ajax == HTTP_X_PARTIAL_XHR
254 // Set special header for ajax == HTTP_X_PARTIAL_XHR
244 YUC.initHeader('X-PARTIAL-XHR',true);
255 YUC.initHeader('X-PARTIAL-XHR',true);
245
256
246 var toQueryString = function(o) {
257 var toQueryString = function(o) {
247 if(typeof o !== 'object') {
258 if(typeof o !== 'object') {
248 return false;
259 return false;
249 }
260 }
250 var _p, _qs = [];
261 var _p, _qs = [];
251 for(_p in o) {
262 for(_p in o) {
252 _qs.push(encodeURIComponent(_p) + '=' + encodeURIComponent(o[_p]));
263 _qs.push(encodeURIComponent(_p) + '=' + encodeURIComponent(o[_p]));
253 }
264 }
254 return _qs.join('&');
265 return _qs.join('&');
255 };
266 };
256
267
257 var sUrl = url;
268 var sUrl = url;
258 var callback = {
269 var callback = {
259 success: success,
270 success: success,
260 failure: function (o) {
271 failure: function (o) {
261 alert("error");
272 alert("error");
262 },
273 },
263 };
274 };
264 var postData = toQueryString(postData);
275 var postData = toQueryString(postData);
265 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
276 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
266 return request;
277 return request;
267 };
278 };
268
279
269
280
270 /**
281 /**
271 * tooltip activate
282 * tooltip activate
272 */
283 */
273 var tooltip_activate = function(){
284 var tooltip_activate = function(){
274 function toolTipsId(){
285 function toolTipsId(){
275 var ids = [];
286 var ids = [];
276 var tts = YUQ('.tooltip');
287 var tts = YUQ('.tooltip');
277 for (var i = 0; i < tts.length; i++) {
288 for (var i = 0; i < tts.length; i++) {
278 // if element doesn't not have and id
289 // if element doesn't not have and id
279 // autogenerate one for tooltip
290 // autogenerate one for tooltip
280 if (!tts[i].id){
291 if (!tts[i].id){
281 tts[i].id='tt'+((i*100)+tts.length);
292 tts[i].id='tt'+((i*100)+tts.length);
282 }
293 }
283 ids.push(tts[i].id);
294 ids.push(tts[i].id);
284 }
295 }
285 return ids
296 return ids
286 };
297 };
287 var myToolTips = new YAHOO.widget.Tooltip("tooltip", {
298 var myToolTips = new YAHOO.widget.Tooltip("tooltip", {
288 context: [[toolTipsId()],"tl","bl",null,[0,5]],
299 context: [[toolTipsId()],"tl","bl",null,[0,5]],
289 monitorresize:false,
300 monitorresize:false,
290 xyoffset :[0,0],
301 xyoffset :[0,0],
291 autodismissdelay:300000,
302 autodismissdelay:300000,
292 hidedelay:5,
303 hidedelay:5,
293 showdelay:20,
304 showdelay:20,
294 });
305 });
295 };
306 };
296
307
297 /**
308 /**
298 * show more
309 * show more
299 */
310 */
300 var show_more_event = function(){
311 var show_more_event = function(){
301 YUE.on(YUD.getElementsByClassName('show_more'),'click',function(e){
312 YUE.on(YUD.getElementsByClassName('show_more'),'click',function(e){
302 var el = e.target;
313 var el = e.target;
303 YUD.setStyle(YUD.get(el.id.substring(1)),'display','');
314 YUD.setStyle(YUD.get(el.id.substring(1)),'display','');
304 YUD.setStyle(el.parentNode,'display','none');
315 YUD.setStyle(el.parentNode,'display','none');
305 });
316 });
306 };
317 };
307
318
308
319
309 /**
320 /**
310 * Quick filter widget
321 * Quick filter widget
311 *
322 *
312 * @param target: filter input target
323 * @param target: filter input target
313 * @param nodes: list of nodes in html we want to filter.
324 * @param nodes: list of nodes in html we want to filter.
314 * @param display_element function that takes current node from nodes and
325 * @param display_element function that takes current node from nodes and
315 * does hide or show based on the node
326 * does hide or show based on the node
316 *
327 *
317 */
328 */
318 var q_filter = function(target,nodes,display_element){
329 var q_filter = function(target,nodes,display_element){
319
330
320 var nodes = nodes;
331 var nodes = nodes;
321 var q_filter_field = YUD.get(target);
332 var q_filter_field = YUD.get(target);
322 var F = YAHOO.namespace(target);
333 var F = YAHOO.namespace(target);
323
334
324 YUE.on(q_filter_field,'click',function(){
335 YUE.on(q_filter_field,'click',function(){
325 q_filter_field.value = '';
336 q_filter_field.value = '';
326 });
337 });
327
338
328 YUE.on(q_filter_field,'keyup',function(e){
339 YUE.on(q_filter_field,'keyup',function(e){
329 clearTimeout(F.filterTimeout);
340 clearTimeout(F.filterTimeout);
330 F.filterTimeout = setTimeout(F.updateFilter,600);
341 F.filterTimeout = setTimeout(F.updateFilter,600);
331 });
342 });
332
343
333 F.filterTimeout = null;
344 F.filterTimeout = null;
334
345
335 var show_node = function(node){
346 var show_node = function(node){
336 YUD.setStyle(node,'display','')
347 YUD.setStyle(node,'display','')
337 }
348 }
338 var hide_node = function(node){
349 var hide_node = function(node){
339 YUD.setStyle(node,'display','none');
350 YUD.setStyle(node,'display','none');
340 }
351 }
341
352
342 F.updateFilter = function() {
353 F.updateFilter = function() {
343 // Reset timeout
354 // Reset timeout
344 F.filterTimeout = null;
355 F.filterTimeout = null;
345
356
346 var obsolete = [];
357 var obsolete = [];
347
358
348 var req = q_filter_field.value.toLowerCase();
359 var req = q_filter_field.value.toLowerCase();
349
360
350 var l = nodes.length;
361 var l = nodes.length;
351 var i;
362 var i;
352 var showing = 0;
363 var showing = 0;
353
364
354 for (i=0;i<l;i++ ){
365 for (i=0;i<l;i++ ){
355 var n = nodes[i];
366 var n = nodes[i];
356 var target_element = display_element(n)
367 var target_element = display_element(n)
357 if(req && n.innerHTML.toLowerCase().indexOf(req) == -1){
368 if(req && n.innerHTML.toLowerCase().indexOf(req) == -1){
358 hide_node(target_element);
369 hide_node(target_element);
359 }
370 }
360 else{
371 else{
361 show_node(target_element);
372 show_node(target_element);
362 showing+=1;
373 showing+=1;
363 }
374 }
364 }
375 }
365
376
366 // if repo_count is set update the number
377 // if repo_count is set update the number
367 var cnt = YUD.get('repo_count');
378 var cnt = YUD.get('repo_count');
368 if(cnt){
379 if(cnt){
369 YUD.get('repo_count').innerHTML = showing;
380 YUD.get('repo_count').innerHTML = showing;
370 }
381 }
371
382
372 }
383 }
373 };
384 };
374
385
375 var tableTr = function(cls, body){
386 var tableTr = function(cls, body){
376 var _el = document.createElement('div');
387 var _el = document.createElement('div');
377 var cont = new YAHOO.util.Element(body);
388 var cont = new YAHOO.util.Element(body);
378 var comment_id = fromHTML(body).children[0].id.split('comment-')[1];
389 var comment_id = fromHTML(body).children[0].id.split('comment-')[1];
379 var id = 'comment-tr-{0}'.format(comment_id);
390 var id = 'comment-tr-{0}'.format(comment_id);
380 var _html = ('<table><tbody><tr id="{0}" class="{1}">'+
391 var _html = ('<table><tbody><tr id="{0}" class="{1}">'+
381 '<td class="lineno-inline new-inline"></td>'+
392 '<td class="lineno-inline new-inline"></td>'+
382 '<td class="lineno-inline old-inline"></td>'+
393 '<td class="lineno-inline old-inline"></td>'+
383 '<td>{2}</td>'+
394 '<td>{2}</td>'+
384 '</tr></tbody></table>').format(id, cls, body);
395 '</tr></tbody></table>').format(id, cls, body);
385 _el.innerHTML = _html;
396 _el.innerHTML = _html;
386 return _el.children[0].children[0].children[0];
397 return _el.children[0].children[0].children[0];
387 };
398 };
388
399
389 /** comments **/
400 /** comments **/
390 var removeInlineForm = function(form) {
401 var removeInlineForm = function(form) {
391 form.parentNode.removeChild(form);
402 form.parentNode.removeChild(form);
392 };
403 };
393
404
394 var createInlineForm = function(parent_tr, f_path, line) {
405 var createInlineForm = function(parent_tr, f_path, line) {
395 var tmpl = YUD.get('comment-inline-form-template').innerHTML;
406 var tmpl = YUD.get('comment-inline-form-template').innerHTML;
396 tmpl = tmpl.format(f_path, line);
407 tmpl = tmpl.format(f_path, line);
397 var form = tableTr('comment-form-inline',tmpl)
408 var form = tableTr('comment-form-inline',tmpl)
398
409
399 // create event for hide button
410 // create event for hide button
400 form = new YAHOO.util.Element(form);
411 form = new YAHOO.util.Element(form);
401 var form_hide_button = new YAHOO.util.Element(YUD.getElementsByClassName('hide-inline-form',null,form)[0]);
412 var form_hide_button = new YAHOO.util.Element(YUD.getElementsByClassName('hide-inline-form',null,form)[0]);
402 form_hide_button.on('click', function(e) {
413 form_hide_button.on('click', function(e) {
403 var newtr = e.currentTarget.parentNode.parentNode.parentNode.parentNode.parentNode;
414 var newtr = e.currentTarget.parentNode.parentNode.parentNode.parentNode.parentNode;
404 if(YUD.hasClass(newtr.nextElementSibling,'inline-comments-button')){
415 if(YUD.hasClass(newtr.nextElementSibling,'inline-comments-button')){
405 YUD.setStyle(newtr.nextElementSibling,'display','');
416 YUD.setStyle(newtr.nextElementSibling,'display','');
406 }
417 }
407 removeInlineForm(newtr);
418 removeInlineForm(newtr);
408 YUD.removeClass(parent_tr, 'form-open');
419 YUD.removeClass(parent_tr, 'form-open');
409
420
410 });
421 });
411
422
412 return form
423 return form
413 };
424 };
414
425
415 /**
426 /**
416 * Inject inline comment for on given TR this tr should be always an .line
427 * Inject inline comment for on given TR this tr should be always an .line
417 * tr containing the line. Code will detect comment, and always put the comment
428 * tr containing the line. Code will detect comment, and always put the comment
418 * block at the very bottom
429 * block at the very bottom
419 */
430 */
420 var injectInlineForm = function(tr){
431 var injectInlineForm = function(tr){
421 if(!YUD.hasClass(tr, 'line')){
432 if(!YUD.hasClass(tr, 'line')){
422 return
433 return
423 }
434 }
424 var submit_url = AJAX_COMMENT_URL;
435 var submit_url = AJAX_COMMENT_URL;
425 var _td = YUD.getElementsByClassName('code',null,tr)[0];
436 var _td = YUD.getElementsByClassName('code',null,tr)[0];
426 if(YUD.hasClass(tr,'form-open') || YUD.hasClass(tr,'context') || YUD.hasClass(_td,'no-comment')){
437 if(YUD.hasClass(tr,'form-open') || YUD.hasClass(tr,'context') || YUD.hasClass(_td,'no-comment')){
427 return
438 return
428 }
439 }
429 YUD.addClass(tr,'form-open');
440 YUD.addClass(tr,'form-open');
430 var node = YUD.getElementsByClassName('full_f_path',null,tr.parentNode.parentNode.parentNode)[0];
441 var node = YUD.getElementsByClassName('full_f_path',null,tr.parentNode.parentNode.parentNode)[0];
431 var f_path = YUD.getAttribute(node,'path');
442 var f_path = YUD.getAttribute(node,'path');
432 var lineno = getLineNo(tr);
443 var lineno = getLineNo(tr);
433 var form = createInlineForm(tr, f_path, lineno, submit_url);
444 var form = createInlineForm(tr, f_path, lineno, submit_url);
434
445
435 var parent = tr;
446 var parent = tr;
436 while (1){
447 while (1){
437 var n = parent.nextElementSibling;
448 var n = parent.nextElementSibling;
438 // next element are comments !
449 // next element are comments !
439 if(YUD.hasClass(n,'inline-comments')){
450 if(YUD.hasClass(n,'inline-comments')){
440 parent = n;
451 parent = n;
441 }
452 }
442 else{
453 else{
443 break;
454 break;
444 }
455 }
445 }
456 }
446 YUD.insertAfter(form,parent);
457 YUD.insertAfter(form,parent);
447 var f = YUD.get(form);
458 var f = YUD.get(form);
448 var overlay = YUD.getElementsByClassName('overlay',null,f)[0];
459 var overlay = YUD.getElementsByClassName('overlay',null,f)[0];
449 var _form = YUD.getElementsByClassName('inline-form',null,f)[0];
460 var _form = YUD.getElementsByClassName('inline-form',null,f)[0];
450
461
451 YUE.on(YUD.get(_form), 'submit',function(e){
462 YUE.on(YUD.get(_form), 'submit',function(e){
452 YUE.preventDefault(e);
463 YUE.preventDefault(e);
453
464
454 //ajax submit
465 //ajax submit
455 var text = YUD.get('text_'+lineno).value;
466 var text = YUD.get('text_'+lineno).value;
456 var postData = {
467 var postData = {
457 'text':text,
468 'text':text,
458 'f_path':f_path,
469 'f_path':f_path,
459 'line':lineno
470 'line':lineno
460 };
471 };
461
472
462 if(lineno === undefined){
473 if(lineno === undefined){
463 alert('missing line !');
474 alert('missing line !');
464 return
475 return
465 }
476 }
466 if(f_path === undefined){
477 if(f_path === undefined){
467 alert('missing file path !');
478 alert('missing file path !');
468 return
479 return
469 }
480 }
470
481
471 if(text == ""){
482 if(text == ""){
472 return
483 return
473 }
484 }
474
485
475 var success = function(o){
486 var success = function(o){
476 YUD.removeClass(tr, 'form-open');
487 YUD.removeClass(tr, 'form-open');
477 removeInlineForm(f);
488 removeInlineForm(f);
478 var json_data = JSON.parse(o.responseText);
489 var json_data = JSON.parse(o.responseText);
479 renderInlineComment(json_data);
490 renderInlineComment(json_data);
480 };
491 };
481
492
482 if (YUD.hasClass(overlay,'overlay')){
493 if (YUD.hasClass(overlay,'overlay')){
483 var w = _form.offsetWidth;
494 var w = _form.offsetWidth;
484 var h = _form.offsetHeight;
495 var h = _form.offsetHeight;
485 YUD.setStyle(overlay,'width',w+'px');
496 YUD.setStyle(overlay,'width',w+'px');
486 YUD.setStyle(overlay,'height',h+'px');
497 YUD.setStyle(overlay,'height',h+'px');
487 }
498 }
488 YUD.addClass(overlay, 'submitting');
499 YUD.addClass(overlay, 'submitting');
489
500
490 ajaxPOST(submit_url, postData, success);
501 ajaxPOST(submit_url, postData, success);
491 });
502 });
492
503
493 setTimeout(function(){
504 setTimeout(function(){
494 // callbacks
505 // callbacks
495 tooltip_activate();
506 tooltip_activate();
496 MentionsAutoComplete('text_'+lineno, 'mentions_container_'+lineno,
507 MentionsAutoComplete('text_'+lineno, 'mentions_container_'+lineno,
497 _USERS_AC_DATA, _GROUPS_AC_DATA);
508 _USERS_AC_DATA, _GROUPS_AC_DATA);
498 var _e = YUD.get('text_'+lineno);
509 var _e = YUD.get('text_'+lineno);
499 if(_e){
510 if(_e){
500 _e.focus();
511 _e.focus();
501 }
512 }
502 },10)
513 },10)
503 };
514 };
504
515
505 var deleteComment = function(comment_id){
516 var deleteComment = function(comment_id){
506 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__',comment_id);
517 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__',comment_id);
507 var postData = {'_method':'delete'};
518 var postData = {'_method':'delete'};
508 var success = function(o){
519 var success = function(o){
509 var n = YUD.get('comment-tr-'+comment_id);
520 var n = YUD.get('comment-tr-'+comment_id);
510 var root = prevElementSibling(prevElementSibling(n));
521 var root = prevElementSibling(prevElementSibling(n));
511 n.parentNode.removeChild(n);
522 n.parentNode.removeChild(n);
512
523
513 // scann nodes, and attach add button to last one
524 // scann nodes, and attach add button to last one
514 placeAddButton(root);
525 placeAddButton(root);
515 }
526 }
516 ajaxPOST(url,postData,success);
527 ajaxPOST(url,postData,success);
517 }
528 }
518
529
519 var updateReviewers = function(reviewers_ids){
530 var updateReviewers = function(reviewers_ids){
520 var url = AJAX_UPDATE_PULLREQUEST;
531 var url = AJAX_UPDATE_PULLREQUEST;
521 var postData = {'_method':'put',
532 var postData = {'_method':'put',
522 'reviewers_ids': reviewers_ids};
533 'reviewers_ids': reviewers_ids};
523 var success = function(o){
534 var success = function(o){
524 window.location.reload();
535 window.location.reload();
525 }
536 }
526 ajaxPOST(url,postData,success);
537 ajaxPOST(url,postData,success);
527 }
538 }
528
539
529 var createInlineAddButton = function(tr){
540 var createInlineAddButton = function(tr){
530
541
531 var label = TRANSLATION_MAP['add another comment'];
542 var label = TRANSLATION_MAP['add another comment'];
532
543
533 var html_el = document.createElement('div');
544 var html_el = document.createElement('div');
534 YUD.addClass(html_el, 'add-comment');
545 YUD.addClass(html_el, 'add-comment');
535 html_el.innerHTML = '<span class="ui-btn">{0}</span>'.format(label);
546 html_el.innerHTML = '<span class="ui-btn">{0}</span>'.format(label);
536
547
537 var add = new YAHOO.util.Element(html_el);
548 var add = new YAHOO.util.Element(html_el);
538 add.on('click', function(e) {
549 add.on('click', function(e) {
539 injectInlineForm(tr);
550 injectInlineForm(tr);
540 });
551 });
541 return add;
552 return add;
542 };
553 };
543
554
544 var getLineNo = function(tr) {
555 var getLineNo = function(tr) {
545 var line;
556 var line;
546 var o = tr.children[0].id.split('_');
557 var o = tr.children[0].id.split('_');
547 var n = tr.children[1].id.split('_');
558 var n = tr.children[1].id.split('_');
548
559
549 if (n.length >= 2) {
560 if (n.length >= 2) {
550 line = n[n.length-1];
561 line = n[n.length-1];
551 } else if (o.length >= 2) {
562 } else if (o.length >= 2) {
552 line = o[o.length-1];
563 line = o[o.length-1];
553 }
564 }
554
565
555 return line
566 return line
556 };
567 };
557
568
558 var placeAddButton = function(target_tr){
569 var placeAddButton = function(target_tr){
559 if(!target_tr){
570 if(!target_tr){
560 return
571 return
561 }
572 }
562 var last_node = target_tr;
573 var last_node = target_tr;
563 //scann
574 //scann
564 while (1){
575 while (1){
565 var n = last_node.nextElementSibling;
576 var n = last_node.nextElementSibling;
566 // next element are comments !
577 // next element are comments !
567 if(YUD.hasClass(n,'inline-comments')){
578 if(YUD.hasClass(n,'inline-comments')){
568 last_node = n;
579 last_node = n;
569 //also remove the comment button from previous
580 //also remove the comment button from previous
570 var comment_add_buttons = YUD.getElementsByClassName('add-comment',null,last_node);
581 var comment_add_buttons = YUD.getElementsByClassName('add-comment',null,last_node);
571 for(var i=0;i<comment_add_buttons.length;i++){
582 for(var i=0;i<comment_add_buttons.length;i++){
572 var b = comment_add_buttons[i];
583 var b = comment_add_buttons[i];
573 b.parentNode.removeChild(b);
584 b.parentNode.removeChild(b);
574 }
585 }
575 }
586 }
576 else{
587 else{
577 break;
588 break;
578 }
589 }
579 }
590 }
580
591
581 var add = createInlineAddButton(target_tr);
592 var add = createInlineAddButton(target_tr);
582 // get the comment div
593 // get the comment div
583 var comment_block = YUD.getElementsByClassName('comment',null,last_node)[0];
594 var comment_block = YUD.getElementsByClassName('comment',null,last_node)[0];
584 // attach add button
595 // attach add button
585 YUD.insertAfter(add,comment_block);
596 YUD.insertAfter(add,comment_block);
586 }
597 }
587
598
588 /**
599 /**
589 * Places the inline comment into the changeset block in proper line position
600 * Places the inline comment into the changeset block in proper line position
590 */
601 */
591 var placeInline = function(target_container,lineno,html){
602 var placeInline = function(target_container,lineno,html){
592 var lineid = "{0}_{1}".format(target_container,lineno);
603 var lineid = "{0}_{1}".format(target_container,lineno);
593 var target_line = YUD.get(lineid);
604 var target_line = YUD.get(lineid);
594 var comment = new YAHOO.util.Element(tableTr('inline-comments',html))
605 var comment = new YAHOO.util.Element(tableTr('inline-comments',html))
595
606
596 // check if there are comments already !
607 // check if there are comments already !
597 var parent = target_line.parentNode;
608 var parent = target_line.parentNode;
598 var root_parent = parent;
609 var root_parent = parent;
599 while (1){
610 while (1){
600 var n = parent.nextElementSibling;
611 var n = parent.nextElementSibling;
601 // next element are comments !
612 // next element are comments !
602 if(YUD.hasClass(n,'inline-comments')){
613 if(YUD.hasClass(n,'inline-comments')){
603 parent = n;
614 parent = n;
604 }
615 }
605 else{
616 else{
606 break;
617 break;
607 }
618 }
608 }
619 }
609 // put in the comment at the bottom
620 // put in the comment at the bottom
610 YUD.insertAfter(comment,parent);
621 YUD.insertAfter(comment,parent);
611
622
612 // scann nodes, and attach add button to last one
623 // scann nodes, and attach add button to last one
613 placeAddButton(root_parent);
624 placeAddButton(root_parent);
614
625
615 return target_line;
626 return target_line;
616 }
627 }
617
628
618 /**
629 /**
619 * make a single inline comment and place it inside
630 * make a single inline comment and place it inside
620 */
631 */
621 var renderInlineComment = function(json_data){
632 var renderInlineComment = function(json_data){
622 try{
633 try{
623 var html = json_data['rendered_text'];
634 var html = json_data['rendered_text'];
624 var lineno = json_data['line_no'];
635 var lineno = json_data['line_no'];
625 var target_id = json_data['target_id'];
636 var target_id = json_data['target_id'];
626 placeInline(target_id, lineno, html);
637 placeInline(target_id, lineno, html);
627
638
628 }catch(e){
639 }catch(e){
629 console.log(e);
640 console.log(e);
630 }
641 }
631 }
642 }
632
643
633 /**
644 /**
634 * Iterates over all the inlines, and places them inside proper blocks of data
645 * Iterates over all the inlines, and places them inside proper blocks of data
635 */
646 */
636 var renderInlineComments = function(file_comments){
647 var renderInlineComments = function(file_comments){
637 for (f in file_comments){
648 for (f in file_comments){
638 // holding all comments for a FILE
649 // holding all comments for a FILE
639 var box = file_comments[f];
650 var box = file_comments[f];
640
651
641 var target_id = YUD.getAttribute(box,'target_id');
652 var target_id = YUD.getAttribute(box,'target_id');
642 // actually comments with line numbers
653 // actually comments with line numbers
643 var comments = box.children;
654 var comments = box.children;
644 for(var i=0; i<comments.length; i++){
655 for(var i=0; i<comments.length; i++){
645 var data = {
656 var data = {
646 'rendered_text': comments[i].outerHTML,
657 'rendered_text': comments[i].outerHTML,
647 'line_no': YUD.getAttribute(comments[i],'line'),
658 'line_no': YUD.getAttribute(comments[i],'line'),
648 'target_id': target_id
659 'target_id': target_id
649 }
660 }
650 renderInlineComment(data);
661 renderInlineComment(data);
651 }
662 }
652 }
663 }
653 }
664 }
654
665
655 var removeReviewer = function(reviewer_id){
666 var removeReviewer = function(reviewer_id){
656 var el = YUD.get('reviewer_{0}'.format(reviewer_id));
667 var el = YUD.get('reviewer_{0}'.format(reviewer_id));
657 if (el.parentNode !== undefined){
668 if (el.parentNode !== undefined){
658 el.parentNode.removeChild(el);
669 el.parentNode.removeChild(el);
659 }
670 }
660 }
671 }
661
672
662 var fileBrowserListeners = function(current_url, node_list_url, url_base){
673 var fileBrowserListeners = function(current_url, node_list_url, url_base){
663
674
664 var current_url_branch = +"?branch=__BRANCH__";
675 var current_url_branch = +"?branch=__BRANCH__";
665 var url = url_base;
676 var url = url_base;
666 var node_url = node_list_url;
677 var node_url = node_list_url;
667
678
668 YUE.on('stay_at_branch','click',function(e){
679 YUE.on('stay_at_branch','click',function(e){
669 if(e.target.checked){
680 if(e.target.checked){
670 var uri = current_url_branch;
681 var uri = current_url_branch;
671 uri = uri.replace('__BRANCH__',e.target.value);
682 uri = uri.replace('__BRANCH__',e.target.value);
672 window.location = uri;
683 window.location = uri;
673 }
684 }
674 else{
685 else{
675 window.location = current_url;
686 window.location = current_url;
676 }
687 }
677 })
688 })
678
689
679 var n_filter = YUD.get('node_filter');
690 var n_filter = YUD.get('node_filter');
680 var F = YAHOO.namespace('node_filter');
691 var F = YAHOO.namespace('node_filter');
681
692
682 F.filterTimeout = null;
693 F.filterTimeout = null;
683 var nodes = null;
694 var nodes = null;
684
695
685 F.initFilter = function(){
696 F.initFilter = function(){
686 YUD.setStyle('node_filter_box_loading','display','');
697 YUD.setStyle('node_filter_box_loading','display','');
687 YUD.setStyle('search_activate_id','display','none');
698 YUD.setStyle('search_activate_id','display','none');
688 YUD.setStyle('add_node_id','display','none');
699 YUD.setStyle('add_node_id','display','none');
689 YUC.initHeader('X-PARTIAL-XHR',true);
700 YUC.initHeader('X-PARTIAL-XHR',true);
690 YUC.asyncRequest('GET',url,{
701 YUC.asyncRequest('GET',url,{
691 success:function(o){
702 success:function(o){
692 nodes = JSON.parse(o.responseText).nodes;
703 nodes = JSON.parse(o.responseText).nodes;
693 YUD.setStyle('node_filter_box_loading','display','none');
704 YUD.setStyle('node_filter_box_loading','display','none');
694 YUD.setStyle('node_filter_box','display','');
705 YUD.setStyle('node_filter_box','display','');
695 n_filter.focus();
706 n_filter.focus();
696 if(YUD.hasClass(n_filter,'init')){
707 if(YUD.hasClass(n_filter,'init')){
697 n_filter.value = '';
708 n_filter.value = '';
698 YUD.removeClass(n_filter,'init');
709 YUD.removeClass(n_filter,'init');
699 }
710 }
700 },
711 },
701 failure:function(o){
712 failure:function(o){
702 console.log('failed to load');
713 console.log('failed to load');
703 }
714 }
704 },null);
715 },null);
705 }
716 }
706
717
707 F.updateFilter = function(e) {
718 F.updateFilter = function(e) {
708
719
709 return function(){
720 return function(){
710 // Reset timeout
721 // Reset timeout
711 F.filterTimeout = null;
722 F.filterTimeout = null;
712 var query = e.target.value.toLowerCase();
723 var query = e.target.value.toLowerCase();
713 var match = [];
724 var match = [];
714 var matches = 0;
725 var matches = 0;
715 var matches_max = 20;
726 var matches_max = 20;
716 if (query != ""){
727 if (query != ""){
717 for(var i=0;i<nodes.length;i++){
728 for(var i=0;i<nodes.length;i++){
718
729
719 var pos = nodes[i].name.toLowerCase().indexOf(query)
730 var pos = nodes[i].name.toLowerCase().indexOf(query)
720 if(query && pos != -1){
731 if(query && pos != -1){
721
732
722 matches++
733 matches++
723 //show only certain amount to not kill browser
734 //show only certain amount to not kill browser
724 if (matches > matches_max){
735 if (matches > matches_max){
725 break;
736 break;
726 }
737 }
727
738
728 var n = nodes[i].name;
739 var n = nodes[i].name;
729 var t = nodes[i].type;
740 var t = nodes[i].type;
730 var n_hl = n.substring(0,pos)
741 var n_hl = n.substring(0,pos)
731 +"<b>{0}</b>".format(n.substring(pos,pos+query.length))
742 +"<b>{0}</b>".format(n.substring(pos,pos+query.length))
732 +n.substring(pos+query.length)
743 +n.substring(pos+query.length)
733 node_url = node_url.replace('__FPATH__',n);
744 node_url = node_url.replace('__FPATH__',n);
734 match.push('<tr><td><a class="browser-{0}" href="{1}">{2}</a></td><td colspan="5"></td></tr>'.format(t,node_url,n_hl));
745 match.push('<tr><td><a class="browser-{0}" href="{1}">{2}</a></td><td colspan="5"></td></tr>'.format(t,node_url,n_hl));
735 }
746 }
736 if(match.length >= matches_max){
747 if(match.length >= matches_max){
737 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['search truncated']));
748 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['search truncated']));
738 }
749 }
739 }
750 }
740 }
751 }
741 if(query != ""){
752 if(query != ""){
742 YUD.setStyle('tbody','display','none');
753 YUD.setStyle('tbody','display','none');
743 YUD.setStyle('tbody_filtered','display','');
754 YUD.setStyle('tbody_filtered','display','');
744
755
745 if (match.length==0){
756 if (match.length==0){
746 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['no matching files']));
757 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['no matching files']));
747 }
758 }
748
759
749 YUD.get('tbody_filtered').innerHTML = match.join("");
760 YUD.get('tbody_filtered').innerHTML = match.join("");
750 }
761 }
751 else{
762 else{
752 YUD.setStyle('tbody','display','');
763 YUD.setStyle('tbody','display','');
753 YUD.setStyle('tbody_filtered','display','none');
764 YUD.setStyle('tbody_filtered','display','none');
754 }
765 }
755
766
756 }
767 }
757 };
768 };
758
769
759 YUE.on(YUD.get('filter_activate'),'click',function(){
770 YUE.on(YUD.get('filter_activate'),'click',function(){
760 F.initFilter();
771 F.initFilter();
761 })
772 })
762 YUE.on(n_filter,'click',function(){
773 YUE.on(n_filter,'click',function(){
763 if(YUD.hasClass(n_filter,'init')){
774 if(YUD.hasClass(n_filter,'init')){
764 n_filter.value = '';
775 n_filter.value = '';
765 YUD.removeClass(n_filter,'init');
776 YUD.removeClass(n_filter,'init');
766 }
777 }
767 });
778 });
768 YUE.on(n_filter,'keyup',function(e){
779 YUE.on(n_filter,'keyup',function(e){
769 clearTimeout(F.filterTimeout);
780 clearTimeout(F.filterTimeout);
770 F.filterTimeout = setTimeout(F.updateFilter(e),600);
781 F.filterTimeout = setTimeout(F.updateFilter(e),600);
771 });
782 });
772 };
783 };
773
784
774
785
775 var initCodeMirror = function(textAreadId,resetUrl){
786 var initCodeMirror = function(textAreadId,resetUrl){
776 var myCodeMirror = CodeMirror.fromTextArea(YUD.get(textAreadId),{
787 var myCodeMirror = CodeMirror.fromTextArea(YUD.get(textAreadId),{
777 mode: "null",
788 mode: "null",
778 lineNumbers:true
789 lineNumbers:true
779 });
790 });
780 YUE.on('reset','click',function(e){
791 YUE.on('reset','click',function(e){
781 window.location=resetUrl
792 window.location=resetUrl
782 });
793 });
783
794
784 YUE.on('file_enable','click',function(){
795 YUE.on('file_enable','click',function(){
785 YUD.setStyle('editor_container','display','');
796 YUD.setStyle('editor_container','display','');
786 YUD.setStyle('upload_file_container','display','none');
797 YUD.setStyle('upload_file_container','display','none');
787 YUD.setStyle('filename_container','display','');
798 YUD.setStyle('filename_container','display','');
788 });
799 });
789
800
790 YUE.on('upload_file_enable','click',function(){
801 YUE.on('upload_file_enable','click',function(){
791 YUD.setStyle('editor_container','display','none');
802 YUD.setStyle('editor_container','display','none');
792 YUD.setStyle('upload_file_container','display','');
803 YUD.setStyle('upload_file_container','display','');
793 YUD.setStyle('filename_container','display','none');
804 YUD.setStyle('filename_container','display','none');
794 });
805 });
795 };
806 };
796
807
797
808
798
809
799 var getIdentNode = function(n){
810 var getIdentNode = function(n){
800 //iterate thru nodes untill matched interesting node !
811 //iterate thru nodes untill matched interesting node !
801
812
802 if (typeof n == 'undefined'){
813 if (typeof n == 'undefined'){
803 return -1
814 return -1
804 }
815 }
805
816
806 if(typeof n.id != "undefined" && n.id.match('L[0-9]+')){
817 if(typeof n.id != "undefined" && n.id.match('L[0-9]+')){
807 return n
818 return n
808 }
819 }
809 else{
820 else{
810 return getIdentNode(n.parentNode);
821 return getIdentNode(n.parentNode);
811 }
822 }
812 };
823 };
813
824
814 var getSelectionLink = function(selection_link_label) {
825 var getSelectionLink = function(selection_link_label) {
815 return function(){
826 return function(){
816 //get selection from start/to nodes
827 //get selection from start/to nodes
817 if (typeof window.getSelection != "undefined") {
828 if (typeof window.getSelection != "undefined") {
818 s = window.getSelection();
829 s = window.getSelection();
819
830
820 from = getIdentNode(s.anchorNode);
831 from = getIdentNode(s.anchorNode);
821 till = getIdentNode(s.focusNode);
832 till = getIdentNode(s.focusNode);
822
833
823 f_int = parseInt(from.id.replace('L',''));
834 f_int = parseInt(from.id.replace('L',''));
824 t_int = parseInt(till.id.replace('L',''));
835 t_int = parseInt(till.id.replace('L',''));
825
836
826 if (f_int > t_int){
837 if (f_int > t_int){
827 //highlight from bottom
838 //highlight from bottom
828 offset = -35;
839 offset = -35;
829 ranges = [t_int,f_int];
840 ranges = [t_int,f_int];
830
841
831 }
842 }
832 else{
843 else{
833 //highligth from top
844 //highligth from top
834 offset = 35;
845 offset = 35;
835 ranges = [f_int,t_int];
846 ranges = [f_int,t_int];
836 }
847 }
837
848
838 if (ranges[0] != ranges[1]){
849 if (ranges[0] != ranges[1]){
839 if(YUD.get('linktt') == null){
850 if(YUD.get('linktt') == null){
840 hl_div = document.createElement('div');
851 hl_div = document.createElement('div');
841 hl_div.id = 'linktt';
852 hl_div.id = 'linktt';
842 }
853 }
843 anchor = '#L'+ranges[0]+'-'+ranges[1];
854 anchor = '#L'+ranges[0]+'-'+ranges[1];
844 hl_div.innerHTML = '';
855 hl_div.innerHTML = '';
845 l = document.createElement('a');
856 l = document.createElement('a');
846 l.href = location.href.substring(0,location.href.indexOf('#'))+anchor;
857 l.href = location.href.substring(0,location.href.indexOf('#'))+anchor;
847 l.innerHTML = selection_link_label;
858 l.innerHTML = selection_link_label;
848 hl_div.appendChild(l);
859 hl_div.appendChild(l);
849
860
850 YUD.get('body').appendChild(hl_div);
861 YUD.get('body').appendChild(hl_div);
851
862
852 xy = YUD.getXY(till.id);
863 xy = YUD.getXY(till.id);
853
864
854 YUD.addClass('linktt','yui-tt');
865 YUD.addClass('linktt','yui-tt');
855 YUD.setStyle('linktt','top',xy[1]+offset+'px');
866 YUD.setStyle('linktt','top',xy[1]+offset+'px');
856 YUD.setStyle('linktt','left',xy[0]+'px');
867 YUD.setStyle('linktt','left',xy[0]+'px');
857 YUD.setStyle('linktt','visibility','visible');
868 YUD.setStyle('linktt','visibility','visible');
858 }
869 }
859 else{
870 else{
860 YUD.setStyle('linktt','visibility','hidden');
871 YUD.setStyle('linktt','visibility','hidden');
861 }
872 }
862 }
873 }
863 }
874 }
864 };
875 };
865
876
866 var deleteNotification = function(url, notification_id,callbacks){
877 var deleteNotification = function(url, notification_id,callbacks){
867 var callback = {
878 var callback = {
868 success:function(o){
879 success:function(o){
869 var obj = YUD.get(String("notification_"+notification_id));
880 var obj = YUD.get(String("notification_"+notification_id));
870 if(obj.parentNode !== undefined){
881 if(obj.parentNode !== undefined){
871 obj.parentNode.removeChild(obj);
882 obj.parentNode.removeChild(obj);
872 }
883 }
873 _run_callbacks(callbacks);
884 _run_callbacks(callbacks);
874 },
885 },
875 failure:function(o){
886 failure:function(o){
876 alert("error");
887 alert("error");
877 },
888 },
878 };
889 };
879 var postData = '_method=delete';
890 var postData = '_method=delete';
880 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
891 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
881 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl,
892 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl,
882 callback, postData);
893 callback, postData);
883 };
894 };
884
895
885 var readNotification = function(url, notification_id,callbacks){
896 var readNotification = function(url, notification_id,callbacks){
886 var callback = {
897 var callback = {
887 success:function(o){
898 success:function(o){
888 var obj = YUD.get(String("notification_"+notification_id));
899 var obj = YUD.get(String("notification_"+notification_id));
889 YUD.removeClass(obj, 'unread');
900 YUD.removeClass(obj, 'unread');
890 var r_button = YUD.getElementsByClassName('read-notification',null,obj.children[0])[0];
901 var r_button = YUD.getElementsByClassName('read-notification',null,obj.children[0])[0];
891
902
892 if(r_button.parentNode !== undefined){
903 if(r_button.parentNode !== undefined){
893 r_button.parentNode.removeChild(r_button);
904 r_button.parentNode.removeChild(r_button);
894 }
905 }
895 _run_callbacks(callbacks);
906 _run_callbacks(callbacks);
896 },
907 },
897 failure:function(o){
908 failure:function(o){
898 alert("error");
909 alert("error");
899 },
910 },
900 };
911 };
901 var postData = '_method=put';
912 var postData = '_method=put';
902 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
913 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
903 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl,
914 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl,
904 callback, postData);
915 callback, postData);
905 };
916 };
906
917
907 /** MEMBERS AUTOCOMPLETE WIDGET **/
918 /** MEMBERS AUTOCOMPLETE WIDGET **/
908
919
909 var MembersAutoComplete = function (divid, cont, users_list, groups_list) {
920 var MembersAutoComplete = function (divid, cont, users_list, groups_list) {
910 var myUsers = users_list;
921 var myUsers = users_list;
911 var myGroups = groups_list;
922 var myGroups = groups_list;
912
923
913 // Define a custom search function for the DataSource of users
924 // Define a custom search function for the DataSource of users
914 var matchUsers = function (sQuery) {
925 var matchUsers = function (sQuery) {
915 // Case insensitive matching
926 // Case insensitive matching
916 var query = sQuery.toLowerCase();
927 var query = sQuery.toLowerCase();
917 var i = 0;
928 var i = 0;
918 var l = myUsers.length;
929 var l = myUsers.length;
919 var matches = [];
930 var matches = [];
920
931
921 // Match against each name of each contact
932 // Match against each name of each contact
922 for (; i < l; i++) {
933 for (; i < l; i++) {
923 contact = myUsers[i];
934 contact = myUsers[i];
924 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
935 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
925 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
936 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
926 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
937 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
927 matches[matches.length] = contact;
938 matches[matches.length] = contact;
928 }
939 }
929 }
940 }
930 return matches;
941 return matches;
931 };
942 };
932
943
933 // Define a custom search function for the DataSource of usersGroups
944 // Define a custom search function for the DataSource of usersGroups
934 var matchGroups = function (sQuery) {
945 var matchGroups = function (sQuery) {
935 // Case insensitive matching
946 // Case insensitive matching
936 var query = sQuery.toLowerCase();
947 var query = sQuery.toLowerCase();
937 var i = 0;
948 var i = 0;
938 var l = myGroups.length;
949 var l = myGroups.length;
939 var matches = [];
950 var matches = [];
940
951
941 // Match against each name of each contact
952 // Match against each name of each contact
942 for (; i < l; i++) {
953 for (; i < l; i++) {
943 matched_group = myGroups[i];
954 matched_group = myGroups[i];
944 if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
955 if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
945 matches[matches.length] = matched_group;
956 matches[matches.length] = matched_group;
946 }
957 }
947 }
958 }
948 return matches;
959 return matches;
949 };
960 };
950
961
951 //match all
962 //match all
952 var matchAll = function (sQuery) {
963 var matchAll = function (sQuery) {
953 u = matchUsers(sQuery);
964 u = matchUsers(sQuery);
954 g = matchGroups(sQuery);
965 g = matchGroups(sQuery);
955 return u.concat(g);
966 return u.concat(g);
956 };
967 };
957
968
958 // DataScheme for members
969 // DataScheme for members
959 var memberDS = new YAHOO.util.FunctionDataSource(matchAll);
970 var memberDS = new YAHOO.util.FunctionDataSource(matchAll);
960 memberDS.responseSchema = {
971 memberDS.responseSchema = {
961 fields: ["id", "fname", "lname", "nname", "grname", "grmembers", "gravatar_lnk"]
972 fields: ["id", "fname", "lname", "nname", "grname", "grmembers", "gravatar_lnk"]
962 };
973 };
963
974
964 // DataScheme for owner
975 // DataScheme for owner
965 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
976 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
966 ownerDS.responseSchema = {
977 ownerDS.responseSchema = {
967 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
978 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
968 };
979 };
969
980
970 // Instantiate AutoComplete for perms
981 // Instantiate AutoComplete for perms
971 var membersAC = new YAHOO.widget.AutoComplete(divid, cont, memberDS);
982 var membersAC = new YAHOO.widget.AutoComplete(divid, cont, memberDS);
972 membersAC.useShadow = false;
983 membersAC.useShadow = false;
973 membersAC.resultTypeList = false;
984 membersAC.resultTypeList = false;
974 membersAC.animVert = false;
985 membersAC.animVert = false;
975 membersAC.animHoriz = false;
986 membersAC.animHoriz = false;
976 membersAC.animSpeed = 0.1;
987 membersAC.animSpeed = 0.1;
977
988
978 // Instantiate AutoComplete for owner
989 // Instantiate AutoComplete for owner
979 var ownerAC = new YAHOO.widget.AutoComplete("user", "owner_container", ownerDS);
990 var ownerAC = new YAHOO.widget.AutoComplete("user", "owner_container", ownerDS);
980 ownerAC.useShadow = false;
991 ownerAC.useShadow = false;
981 ownerAC.resultTypeList = false;
992 ownerAC.resultTypeList = false;
982 ownerAC.animVert = false;
993 ownerAC.animVert = false;
983 ownerAC.animHoriz = false;
994 ownerAC.animHoriz = false;
984 ownerAC.animSpeed = 0.1;
995 ownerAC.animSpeed = 0.1;
985
996
986 // Helper highlight function for the formatter
997 // Helper highlight function for the formatter
987 var highlightMatch = function (full, snippet, matchindex) {
998 var highlightMatch = function (full, snippet, matchindex) {
988 return full.substring(0, matchindex)
999 return full.substring(0, matchindex)
989 + "<span class='match'>"
1000 + "<span class='match'>"
990 + full.substr(matchindex, snippet.length)
1001 + full.substr(matchindex, snippet.length)
991 + "</span>" + full.substring(matchindex + snippet.length);
1002 + "</span>" + full.substring(matchindex + snippet.length);
992 };
1003 };
993
1004
994 // Custom formatter to highlight the matching letters
1005 // Custom formatter to highlight the matching letters
995 var custom_formatter = function (oResultData, sQuery, sResultMatch) {
1006 var custom_formatter = function (oResultData, sQuery, sResultMatch) {
996 var query = sQuery.toLowerCase();
1007 var query = sQuery.toLowerCase();
997 var _gravatar = function(res, em, group){
1008 var _gravatar = function(res, em, group){
998 if (group !== undefined){
1009 if (group !== undefined){
999 em = '/images/icons/group.png'
1010 em = '/images/icons/group.png'
1000 }
1011 }
1001 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1012 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1002 return tmpl.format(em,res)
1013 return tmpl.format(em,res)
1003 }
1014 }
1004 // group
1015 // group
1005 if (oResultData.grname != undefined) {
1016 if (oResultData.grname != undefined) {
1006 var grname = oResultData.grname;
1017 var grname = oResultData.grname;
1007 var grmembers = oResultData.grmembers;
1018 var grmembers = oResultData.grmembers;
1008 var grnameMatchIndex = grname.toLowerCase().indexOf(query);
1019 var grnameMatchIndex = grname.toLowerCase().indexOf(query);
1009 var grprefix = "{0}: ".format(_TM['Group']);
1020 var grprefix = "{0}: ".format(_TM['Group']);
1010 var grsuffix = " (" + grmembers + " )";
1021 var grsuffix = " (" + grmembers + " )";
1011 var grsuffix = " ({0} {1})".format(grmembers, _TM['members']);
1022 var grsuffix = " ({0} {1})".format(grmembers, _TM['members']);
1012
1023
1013 if (grnameMatchIndex > -1) {
1024 if (grnameMatchIndex > -1) {
1014 return _gravatar(grprefix + highlightMatch(grname, query, grnameMatchIndex) + grsuffix,null,true);
1025 return _gravatar(grprefix + highlightMatch(grname, query, grnameMatchIndex) + grsuffix,null,true);
1015 }
1026 }
1016 return _gravatar(grprefix + oResultData.grname + grsuffix, null,true);
1027 return _gravatar(grprefix + oResultData.grname + grsuffix, null,true);
1017 // Users
1028 // Users
1018 } else if (oResultData.nname != undefined) {
1029 } else if (oResultData.nname != undefined) {
1019 var fname = oResultData.fname || "";
1030 var fname = oResultData.fname || "";
1020 var lname = oResultData.lname || "";
1031 var lname = oResultData.lname || "";
1021 var nname = oResultData.nname;
1032 var nname = oResultData.nname;
1022
1033
1023 // Guard against null value
1034 // Guard against null value
1024 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1035 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1025 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1036 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1026 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1037 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1027 displayfname, displaylname, displaynname;
1038 displayfname, displaylname, displaynname;
1028
1039
1029 if (fnameMatchIndex > -1) {
1040 if (fnameMatchIndex > -1) {
1030 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1041 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1031 } else {
1042 } else {
1032 displayfname = fname;
1043 displayfname = fname;
1033 }
1044 }
1034
1045
1035 if (lnameMatchIndex > -1) {
1046 if (lnameMatchIndex > -1) {
1036 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1047 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1037 } else {
1048 } else {
1038 displaylname = lname;
1049 displaylname = lname;
1039 }
1050 }
1040
1051
1041 if (nnameMatchIndex > -1) {
1052 if (nnameMatchIndex > -1) {
1042 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1053 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1043 } else {
1054 } else {
1044 displaynname = nname ? "(" + nname + ")" : "";
1055 displaynname = nname ? "(" + nname + ")" : "";
1045 }
1056 }
1046
1057
1047 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1058 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1048 } else {
1059 } else {
1049 return '';
1060 return '';
1050 }
1061 }
1051 };
1062 };
1052 membersAC.formatResult = custom_formatter;
1063 membersAC.formatResult = custom_formatter;
1053 ownerAC.formatResult = custom_formatter;
1064 ownerAC.formatResult = custom_formatter;
1054
1065
1055 var myHandler = function (sType, aArgs) {
1066 var myHandler = function (sType, aArgs) {
1056 var nextId = divid.split('perm_new_member_name_')[1];
1067 var nextId = divid.split('perm_new_member_name_')[1];
1057 var myAC = aArgs[0]; // reference back to the AC instance
1068 var myAC = aArgs[0]; // reference back to the AC instance
1058 var elLI = aArgs[1]; // reference to the selected LI element
1069 var elLI = aArgs[1]; // reference to the selected LI element
1059 var oData = aArgs[2]; // object literal of selected item's result data
1070 var oData = aArgs[2]; // object literal of selected item's result data
1060 //fill the autocomplete with value
1071 //fill the autocomplete with value
1061 if (oData.nname != undefined) {
1072 if (oData.nname != undefined) {
1062 //users
1073 //users
1063 myAC.getInputEl().value = oData.nname;
1074 myAC.getInputEl().value = oData.nname;
1064 YUD.get('perm_new_member_type_'+nextId).value = 'user';
1075 YUD.get('perm_new_member_type_'+nextId).value = 'user';
1065 } else {
1076 } else {
1066 //groups
1077 //groups
1067 myAC.getInputEl().value = oData.grname;
1078 myAC.getInputEl().value = oData.grname;
1068 YUD.get('perm_new_member_type_'+nextId).value = 'users_group';
1079 YUD.get('perm_new_member_type_'+nextId).value = 'users_group';
1069 }
1080 }
1070 };
1081 };
1071
1082
1072 membersAC.itemSelectEvent.subscribe(myHandler);
1083 membersAC.itemSelectEvent.subscribe(myHandler);
1073 if(ownerAC.itemSelectEvent){
1084 if(ownerAC.itemSelectEvent){
1074 ownerAC.itemSelectEvent.subscribe(myHandler);
1085 ownerAC.itemSelectEvent.subscribe(myHandler);
1075 }
1086 }
1076
1087
1077 return {
1088 return {
1078 memberDS: memberDS,
1089 memberDS: memberDS,
1079 ownerDS: ownerDS,
1090 ownerDS: ownerDS,
1080 membersAC: membersAC,
1091 membersAC: membersAC,
1081 ownerAC: ownerAC,
1092 ownerAC: ownerAC,
1082 };
1093 };
1083 }
1094 }
1084
1095
1085
1096
1086 var MentionsAutoComplete = function (divid, cont, users_list, groups_list) {
1097 var MentionsAutoComplete = function (divid, cont, users_list, groups_list) {
1087 var myUsers = users_list;
1098 var myUsers = users_list;
1088 var myGroups = groups_list;
1099 var myGroups = groups_list;
1089
1100
1090 // Define a custom search function for the DataSource of users
1101 // Define a custom search function for the DataSource of users
1091 var matchUsers = function (sQuery) {
1102 var matchUsers = function (sQuery) {
1092 var org_sQuery = sQuery;
1103 var org_sQuery = sQuery;
1093 if(this.mentionQuery == null){
1104 if(this.mentionQuery == null){
1094 return []
1105 return []
1095 }
1106 }
1096 sQuery = this.mentionQuery;
1107 sQuery = this.mentionQuery;
1097 // Case insensitive matching
1108 // Case insensitive matching
1098 var query = sQuery.toLowerCase();
1109 var query = sQuery.toLowerCase();
1099 var i = 0;
1110 var i = 0;
1100 var l = myUsers.length;
1111 var l = myUsers.length;
1101 var matches = [];
1112 var matches = [];
1102
1113
1103 // Match against each name of each contact
1114 // Match against each name of each contact
1104 for (; i < l; i++) {
1115 for (; i < l; i++) {
1105 contact = myUsers[i];
1116 contact = myUsers[i];
1106 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1117 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1107 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1118 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1108 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1119 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1109 matches[matches.length] = contact;
1120 matches[matches.length] = contact;
1110 }
1121 }
1111 }
1122 }
1112 return matches
1123 return matches
1113 };
1124 };
1114
1125
1115 //match all
1126 //match all
1116 var matchAll = function (sQuery) {
1127 var matchAll = function (sQuery) {
1117 u = matchUsers(sQuery);
1128 u = matchUsers(sQuery);
1118 return u
1129 return u
1119 };
1130 };
1120
1131
1121 // DataScheme for owner
1132 // DataScheme for owner
1122 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1133 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1123
1134
1124 ownerDS.responseSchema = {
1135 ownerDS.responseSchema = {
1125 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1136 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1126 };
1137 };
1127
1138
1128 // Instantiate AutoComplete for mentions
1139 // Instantiate AutoComplete for mentions
1129 var ownerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
1140 var ownerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
1130 ownerAC.useShadow = false;
1141 ownerAC.useShadow = false;
1131 ownerAC.resultTypeList = false;
1142 ownerAC.resultTypeList = false;
1132 ownerAC.suppressInputUpdate = true;
1143 ownerAC.suppressInputUpdate = true;
1133 ownerAC.animVert = false;
1144 ownerAC.animVert = false;
1134 ownerAC.animHoriz = false;
1145 ownerAC.animHoriz = false;
1135 ownerAC.animSpeed = 0.1;
1146 ownerAC.animSpeed = 0.1;
1136
1147
1137 // Helper highlight function for the formatter
1148 // Helper highlight function for the formatter
1138 var highlightMatch = function (full, snippet, matchindex) {
1149 var highlightMatch = function (full, snippet, matchindex) {
1139 return full.substring(0, matchindex)
1150 return full.substring(0, matchindex)
1140 + "<span class='match'>"
1151 + "<span class='match'>"
1141 + full.substr(matchindex, snippet.length)
1152 + full.substr(matchindex, snippet.length)
1142 + "</span>" + full.substring(matchindex + snippet.length);
1153 + "</span>" + full.substring(matchindex + snippet.length);
1143 };
1154 };
1144
1155
1145 // Custom formatter to highlight the matching letters
1156 // Custom formatter to highlight the matching letters
1146 ownerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
1157 ownerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
1147 var org_sQuery = sQuery;
1158 var org_sQuery = sQuery;
1148 if(this.dataSource.mentionQuery != null){
1159 if(this.dataSource.mentionQuery != null){
1149 sQuery = this.dataSource.mentionQuery;
1160 sQuery = this.dataSource.mentionQuery;
1150 }
1161 }
1151
1162
1152 var query = sQuery.toLowerCase();
1163 var query = sQuery.toLowerCase();
1153 var _gravatar = function(res, em, group){
1164 var _gravatar = function(res, em, group){
1154 if (group !== undefined){
1165 if (group !== undefined){
1155 em = '/images/icons/group.png'
1166 em = '/images/icons/group.png'
1156 }
1167 }
1157 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1168 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1158 return tmpl.format(em,res)
1169 return tmpl.format(em,res)
1159 }
1170 }
1160 if (oResultData.nname != undefined) {
1171 if (oResultData.nname != undefined) {
1161 var fname = oResultData.fname || "";
1172 var fname = oResultData.fname || "";
1162 var lname = oResultData.lname || "";
1173 var lname = oResultData.lname || "";
1163 var nname = oResultData.nname;
1174 var nname = oResultData.nname;
1164
1175
1165 // Guard against null value
1176 // Guard against null value
1166 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1177 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1167 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1178 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1168 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1179 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1169 displayfname, displaylname, displaynname;
1180 displayfname, displaylname, displaynname;
1170
1181
1171 if (fnameMatchIndex > -1) {
1182 if (fnameMatchIndex > -1) {
1172 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1183 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1173 } else {
1184 } else {
1174 displayfname = fname;
1185 displayfname = fname;
1175 }
1186 }
1176
1187
1177 if (lnameMatchIndex > -1) {
1188 if (lnameMatchIndex > -1) {
1178 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1189 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1179 } else {
1190 } else {
1180 displaylname = lname;
1191 displaylname = lname;
1181 }
1192 }
1182
1193
1183 if (nnameMatchIndex > -1) {
1194 if (nnameMatchIndex > -1) {
1184 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1195 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1185 } else {
1196 } else {
1186 displaynname = nname ? "(" + nname + ")" : "";
1197 displaynname = nname ? "(" + nname + ")" : "";
1187 }
1198 }
1188
1199
1189 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1200 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1190 } else {
1201 } else {
1191 return '';
1202 return '';
1192 }
1203 }
1193 };
1204 };
1194
1205
1195 if(ownerAC.itemSelectEvent){
1206 if(ownerAC.itemSelectEvent){
1196 ownerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1207 ownerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1197
1208
1198 var myAC = aArgs[0]; // reference back to the AC instance
1209 var myAC = aArgs[0]; // reference back to the AC instance
1199 var elLI = aArgs[1]; // reference to the selected LI element
1210 var elLI = aArgs[1]; // reference to the selected LI element
1200 var oData = aArgs[2]; // object literal of selected item's result data
1211 var oData = aArgs[2]; // object literal of selected item's result data
1201 //fill the autocomplete with value
1212 //fill the autocomplete with value
1202 if (oData.nname != undefined) {
1213 if (oData.nname != undefined) {
1203 //users
1214 //users
1204 //Replace the mention name with replaced
1215 //Replace the mention name with replaced
1205 var re = new RegExp();
1216 var re = new RegExp();
1206 var org = myAC.getInputEl().value;
1217 var org = myAC.getInputEl().value;
1207 var chunks = myAC.dataSource.chunks
1218 var chunks = myAC.dataSource.chunks
1208 // replace middle chunk(the search term) with actuall match
1219 // replace middle chunk(the search term) with actuall match
1209 chunks[1] = chunks[1].replace('@'+myAC.dataSource.mentionQuery,
1220 chunks[1] = chunks[1].replace('@'+myAC.dataSource.mentionQuery,
1210 '@'+oData.nname+' ');
1221 '@'+oData.nname+' ');
1211 myAC.getInputEl().value = chunks.join('')
1222 myAC.getInputEl().value = chunks.join('')
1212 YUD.get(myAC.getInputEl()).focus(); // Y U NO WORK !?
1223 YUD.get(myAC.getInputEl()).focus(); // Y U NO WORK !?
1213 } else {
1224 } else {
1214 //groups
1225 //groups
1215 myAC.getInputEl().value = oData.grname;
1226 myAC.getInputEl().value = oData.grname;
1216 YUD.get('perm_new_member_type').value = 'users_group';
1227 YUD.get('perm_new_member_type').value = 'users_group';
1217 }
1228 }
1218 });
1229 });
1219 }
1230 }
1220
1231
1221 // in this keybuffer we will gather current value of search !
1232 // in this keybuffer we will gather current value of search !
1222 // since we need to get this just when someone does `@` then we do the
1233 // since we need to get this just when someone does `@` then we do the
1223 // search
1234 // search
1224 ownerAC.dataSource.chunks = [];
1235 ownerAC.dataSource.chunks = [];
1225 ownerAC.dataSource.mentionQuery = null;
1236 ownerAC.dataSource.mentionQuery = null;
1226
1237
1227 ownerAC.get_mention = function(msg, max_pos) {
1238 ownerAC.get_mention = function(msg, max_pos) {
1228 var org = msg;
1239 var org = msg;
1229 var re = new RegExp('(?:^@|\s@)([a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+)$')
1240 var re = new RegExp('(?:^@|\s@)([a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+)$')
1230 var chunks = [];
1241 var chunks = [];
1231
1242
1232
1243
1233 // cut first chunk until curret pos
1244 // cut first chunk until curret pos
1234 var to_max = msg.substr(0, max_pos);
1245 var to_max = msg.substr(0, max_pos);
1235 var at_pos = Math.max(0,to_max.lastIndexOf('@')-1);
1246 var at_pos = Math.max(0,to_max.lastIndexOf('@')-1);
1236 var msg2 = to_max.substr(at_pos);
1247 var msg2 = to_max.substr(at_pos);
1237
1248
1238 chunks.push(org.substr(0,at_pos))// prefix chunk
1249 chunks.push(org.substr(0,at_pos))// prefix chunk
1239 chunks.push(msg2) // search chunk
1250 chunks.push(msg2) // search chunk
1240 chunks.push(org.substr(max_pos)) // postfix chunk
1251 chunks.push(org.substr(max_pos)) // postfix chunk
1241
1252
1242 // clean up msg2 for filtering and regex match
1253 // clean up msg2 for filtering and regex match
1243 var msg2 = msg2.lstrip(' ').lstrip('\n');
1254 var msg2 = msg2.lstrip(' ').lstrip('\n');
1244
1255
1245 if(re.test(msg2)){
1256 if(re.test(msg2)){
1246 var unam = re.exec(msg2)[1];
1257 var unam = re.exec(msg2)[1];
1247 return [unam, chunks];
1258 return [unam, chunks];
1248 }
1259 }
1249 return [null, null];
1260 return [null, null];
1250 };
1261 };
1251
1262
1252 if (ownerAC.textboxKeyUpEvent){
1263 if (ownerAC.textboxKeyUpEvent){
1253 ownerAC.textboxKeyUpEvent.subscribe(function(type, args){
1264 ownerAC.textboxKeyUpEvent.subscribe(function(type, args){
1254
1265
1255 var ac_obj = args[0];
1266 var ac_obj = args[0];
1256 var currentMessage = args[1];
1267 var currentMessage = args[1];
1257 var currentCaretPosition = args[0]._elTextbox.selectionStart;
1268 var currentCaretPosition = args[0]._elTextbox.selectionStart;
1258
1269
1259 var unam = ownerAC.get_mention(currentMessage, currentCaretPosition);
1270 var unam = ownerAC.get_mention(currentMessage, currentCaretPosition);
1260 var curr_search = null;
1271 var curr_search = null;
1261 if(unam[0]){
1272 if(unam[0]){
1262 curr_search = unam[0];
1273 curr_search = unam[0];
1263 }
1274 }
1264
1275
1265 ownerAC.dataSource.chunks = unam[1];
1276 ownerAC.dataSource.chunks = unam[1];
1266 ownerAC.dataSource.mentionQuery = curr_search;
1277 ownerAC.dataSource.mentionQuery = curr_search;
1267
1278
1268 })
1279 })
1269 }
1280 }
1270 return {
1281 return {
1271 ownerDS: ownerDS,
1282 ownerDS: ownerDS,
1272 ownerAC: ownerAC,
1283 ownerAC: ownerAC,
1273 };
1284 };
1274 }
1285 }
1275
1286
1276
1287
1277 var PullRequestAutoComplete = function (divid, cont, users_list, groups_list) {
1288 var PullRequestAutoComplete = function (divid, cont, users_list, groups_list) {
1278 var myUsers = users_list;
1289 var myUsers = users_list;
1279 var myGroups = groups_list;
1290 var myGroups = groups_list;
1280
1291
1281 // Define a custom search function for the DataSource of users
1292 // Define a custom search function for the DataSource of users
1282 var matchUsers = function (sQuery) {
1293 var matchUsers = function (sQuery) {
1283 // Case insensitive matching
1294 // Case insensitive matching
1284 var query = sQuery.toLowerCase();
1295 var query = sQuery.toLowerCase();
1285 var i = 0;
1296 var i = 0;
1286 var l = myUsers.length;
1297 var l = myUsers.length;
1287 var matches = [];
1298 var matches = [];
1288
1299
1289 // Match against each name of each contact
1300 // Match against each name of each contact
1290 for (; i < l; i++) {
1301 for (; i < l; i++) {
1291 contact = myUsers[i];
1302 contact = myUsers[i];
1292 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1303 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1293 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1304 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1294 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1305 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1295 matches[matches.length] = contact;
1306 matches[matches.length] = contact;
1296 }
1307 }
1297 }
1308 }
1298 return matches;
1309 return matches;
1299 };
1310 };
1300
1311
1301 // Define a custom search function for the DataSource of usersGroups
1312 // Define a custom search function for the DataSource of usersGroups
1302 var matchGroups = function (sQuery) {
1313 var matchGroups = function (sQuery) {
1303 // Case insensitive matching
1314 // Case insensitive matching
1304 var query = sQuery.toLowerCase();
1315 var query = sQuery.toLowerCase();
1305 var i = 0;
1316 var i = 0;
1306 var l = myGroups.length;
1317 var l = myGroups.length;
1307 var matches = [];
1318 var matches = [];
1308
1319
1309 // Match against each name of each contact
1320 // Match against each name of each contact
1310 for (; i < l; i++) {
1321 for (; i < l; i++) {
1311 matched_group = myGroups[i];
1322 matched_group = myGroups[i];
1312 if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
1323 if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
1313 matches[matches.length] = matched_group;
1324 matches[matches.length] = matched_group;
1314 }
1325 }
1315 }
1326 }
1316 return matches;
1327 return matches;
1317 };
1328 };
1318
1329
1319 //match all
1330 //match all
1320 var matchAll = function (sQuery) {
1331 var matchAll = function (sQuery) {
1321 u = matchUsers(sQuery);
1332 u = matchUsers(sQuery);
1322 return u
1333 return u
1323 };
1334 };
1324
1335
1325 // DataScheme for owner
1336 // DataScheme for owner
1326 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1337 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1327
1338
1328 ownerDS.responseSchema = {
1339 ownerDS.responseSchema = {
1329 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1340 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1330 };
1341 };
1331
1342
1332 // Instantiate AutoComplete for mentions
1343 // Instantiate AutoComplete for mentions
1333 var reviewerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
1344 var reviewerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
1334 reviewerAC.useShadow = false;
1345 reviewerAC.useShadow = false;
1335 reviewerAC.resultTypeList = false;
1346 reviewerAC.resultTypeList = false;
1336 reviewerAC.suppressInputUpdate = true;
1347 reviewerAC.suppressInputUpdate = true;
1337 reviewerAC.animVert = false;
1348 reviewerAC.animVert = false;
1338 reviewerAC.animHoriz = false;
1349 reviewerAC.animHoriz = false;
1339 reviewerAC.animSpeed = 0.1;
1350 reviewerAC.animSpeed = 0.1;
1340
1351
1341 // Helper highlight function for the formatter
1352 // Helper highlight function for the formatter
1342 var highlightMatch = function (full, snippet, matchindex) {
1353 var highlightMatch = function (full, snippet, matchindex) {
1343 return full.substring(0, matchindex)
1354 return full.substring(0, matchindex)
1344 + "<span class='match'>"
1355 + "<span class='match'>"
1345 + full.substr(matchindex, snippet.length)
1356 + full.substr(matchindex, snippet.length)
1346 + "</span>" + full.substring(matchindex + snippet.length);
1357 + "</span>" + full.substring(matchindex + snippet.length);
1347 };
1358 };
1348
1359
1349 // Custom formatter to highlight the matching letters
1360 // Custom formatter to highlight the matching letters
1350 reviewerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
1361 reviewerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
1351 var org_sQuery = sQuery;
1362 var org_sQuery = sQuery;
1352 if(this.dataSource.mentionQuery != null){
1363 if(this.dataSource.mentionQuery != null){
1353 sQuery = this.dataSource.mentionQuery;
1364 sQuery = this.dataSource.mentionQuery;
1354 }
1365 }
1355
1366
1356 var query = sQuery.toLowerCase();
1367 var query = sQuery.toLowerCase();
1357 var _gravatar = function(res, em, group){
1368 var _gravatar = function(res, em, group){
1358 if (group !== undefined){
1369 if (group !== undefined){
1359 em = '/images/icons/group.png'
1370 em = '/images/icons/group.png'
1360 }
1371 }
1361 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1372 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1362 return tmpl.format(em,res)
1373 return tmpl.format(em,res)
1363 }
1374 }
1364 if (oResultData.nname != undefined) {
1375 if (oResultData.nname != undefined) {
1365 var fname = oResultData.fname || "";
1376 var fname = oResultData.fname || "";
1366 var lname = oResultData.lname || "";
1377 var lname = oResultData.lname || "";
1367 var nname = oResultData.nname;
1378 var nname = oResultData.nname;
1368
1379
1369 // Guard against null value
1380 // Guard against null value
1370 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1381 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1371 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1382 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1372 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1383 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1373 displayfname, displaylname, displaynname;
1384 displayfname, displaylname, displaynname;
1374
1385
1375 if (fnameMatchIndex > -1) {
1386 if (fnameMatchIndex > -1) {
1376 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1387 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1377 } else {
1388 } else {
1378 displayfname = fname;
1389 displayfname = fname;
1379 }
1390 }
1380
1391
1381 if (lnameMatchIndex > -1) {
1392 if (lnameMatchIndex > -1) {
1382 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1393 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1383 } else {
1394 } else {
1384 displaylname = lname;
1395 displaylname = lname;
1385 }
1396 }
1386
1397
1387 if (nnameMatchIndex > -1) {
1398 if (nnameMatchIndex > -1) {
1388 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1399 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1389 } else {
1400 } else {
1390 displaynname = nname ? "(" + nname + ")" : "";
1401 displaynname = nname ? "(" + nname + ")" : "";
1391 }
1402 }
1392
1403
1393 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1404 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1394 } else {
1405 } else {
1395 return '';
1406 return '';
1396 }
1407 }
1397 };
1408 };
1398
1409
1399 //members cache to catch duplicates
1410 //members cache to catch duplicates
1400 reviewerAC.dataSource.cache = [];
1411 reviewerAC.dataSource.cache = [];
1401 // hack into select event
1412 // hack into select event
1402 if(reviewerAC.itemSelectEvent){
1413 if(reviewerAC.itemSelectEvent){
1403 reviewerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1414 reviewerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1404
1415
1405 var myAC = aArgs[0]; // reference back to the AC instance
1416 var myAC = aArgs[0]; // reference back to the AC instance
1406 var elLI = aArgs[1]; // reference to the selected LI element
1417 var elLI = aArgs[1]; // reference to the selected LI element
1407 var oData = aArgs[2]; // object literal of selected item's result data
1418 var oData = aArgs[2]; // object literal of selected item's result data
1408 var members = YUD.get('review_members');
1419 var members = YUD.get('review_members');
1409 //fill the autocomplete with value
1420 //fill the autocomplete with value
1410
1421
1411 if (oData.nname != undefined) {
1422 if (oData.nname != undefined) {
1412 if (myAC.dataSource.cache.indexOf(oData.id) != -1){
1423 if (myAC.dataSource.cache.indexOf(oData.id) != -1){
1413 return
1424 return
1414 }
1425 }
1415
1426
1416 var tmpl = '<li id="reviewer_{2}">'+
1427 var tmpl = '<li id="reviewer_{2}">'+
1417 '<div class="reviewers_member">'+
1428 '<div class="reviewers_member">'+
1418 '<div class="gravatar"><img alt="gravatar" src="{0}"/> </div>'+
1429 '<div class="gravatar"><img alt="gravatar" src="{0}"/> </div>'+
1419 '<div style="float:left">{1}</div>'+
1430 '<div style="float:left">{1}</div>'+
1420 '<input type="hidden" value="{2}" name="review_members" />'+
1431 '<input type="hidden" value="{2}" name="review_members" />'+
1421 '<span class="delete_icon action_button" onclick="removeReviewer({2})"></span>'+
1432 '<span class="delete_icon action_button" onclick="removeReviewer({2})"></span>'+
1422 '</div>'+
1433 '</div>'+
1423 '</li>'
1434 '</li>'
1424
1435
1425 var displayname = "{0} {1} ({2})".format(oData.fname,oData.lname,oData.nname);
1436 var displayname = "{0} {1} ({2})".format(oData.fname,oData.lname,oData.nname);
1426 var element = tmpl.format(oData.gravatar_lnk,displayname,oData.id);
1437 var element = tmpl.format(oData.gravatar_lnk,displayname,oData.id);
1427 members.innerHTML += element;
1438 members.innerHTML += element;
1428 myAC.dataSource.cache.push(oData.id);
1439 myAC.dataSource.cache.push(oData.id);
1429 YUD.get('user').value = ''
1440 YUD.get('user').value = ''
1430 }
1441 }
1431 });
1442 });
1432 }
1443 }
1433 return {
1444 return {
1434 ownerDS: ownerDS,
1445 ownerDS: ownerDS,
1435 reviewerAC: reviewerAC,
1446 reviewerAC: reviewerAC,
1436 };
1447 };
1437 }
1448 }
1438
1449
1439
1450
1440 /**
1451 /**
1441 * QUICK REPO MENU
1452 * QUICK REPO MENU
1442 */
1453 */
1443 var quick_repo_menu = function(){
1454 var quick_repo_menu = function(){
1444 YUE.on(YUQ('.quick_repo_menu'),'mouseenter',function(e){
1455 YUE.on(YUQ('.quick_repo_menu'),'mouseenter',function(e){
1445 var menu = e.currentTarget.firstElementChild.firstElementChild;
1456 var menu = e.currentTarget.firstElementChild.firstElementChild;
1446 if(YUD.hasClass(menu,'hidden')){
1457 if(YUD.hasClass(menu,'hidden')){
1447 YUD.replaceClass(e.currentTarget,'hidden', 'active');
1458 YUD.replaceClass(e.currentTarget,'hidden', 'active');
1448 YUD.replaceClass(menu, 'hidden', 'active');
1459 YUD.replaceClass(menu, 'hidden', 'active');
1449 }
1460 }
1450 })
1461 })
1451 YUE.on(YUQ('.quick_repo_menu'),'mouseleave',function(e){
1462 YUE.on(YUQ('.quick_repo_menu'),'mouseleave',function(e){
1452 var menu = e.currentTarget.firstElementChild.firstElementChild;
1463 var menu = e.currentTarget.firstElementChild.firstElementChild;
1453 if(YUD.hasClass(menu,'active')){
1464 if(YUD.hasClass(menu,'active')){
1454 YUD.replaceClass(e.currentTarget, 'active', 'hidden');
1465 YUD.replaceClass(e.currentTarget, 'active', 'hidden');
1455 YUD.replaceClass(menu, 'active', 'hidden');
1466 YUD.replaceClass(menu, 'active', 'hidden');
1456 }
1467 }
1457 })
1468 })
1458 };
1469 };
1459
1470
1460
1471
1461 /**
1472 /**
1462 * TABLE SORTING
1473 * TABLE SORTING
1463 */
1474 */
1464
1475
1465 // returns a node from given html;
1476 // returns a node from given html;
1466 var fromHTML = function(html){
1477 var fromHTML = function(html){
1467 var _html = document.createElement('element');
1478 var _html = document.createElement('element');
1468 _html.innerHTML = html;
1479 _html.innerHTML = html;
1469 return _html;
1480 return _html;
1470 }
1481 }
1471 var get_rev = function(node){
1482 var get_rev = function(node){
1472 var n = node.firstElementChild.firstElementChild;
1483 var n = node.firstElementChild.firstElementChild;
1473
1484
1474 if (n===null){
1485 if (n===null){
1475 return -1
1486 return -1
1476 }
1487 }
1477 else{
1488 else{
1478 out = n.firstElementChild.innerHTML.split(':')[0].replace('r','');
1489 out = n.firstElementChild.innerHTML.split(':')[0].replace('r','');
1479 return parseInt(out);
1490 return parseInt(out);
1480 }
1491 }
1481 }
1492 }
1482
1493
1483 var get_name = function(node){
1494 var get_name = function(node){
1484 var name = node.firstElementChild.children[2].innerHTML;
1495 var name = node.firstElementChild.children[2].innerHTML;
1485 return name
1496 return name
1486 }
1497 }
1487 var get_group_name = function(node){
1498 var get_group_name = function(node){
1488 var name = node.firstElementChild.children[1].innerHTML;
1499 var name = node.firstElementChild.children[1].innerHTML;
1489 return name
1500 return name
1490 }
1501 }
1491 var get_date = function(node){
1502 var get_date = function(node){
1492 var date_ = YUD.getAttribute(node.firstElementChild,'date');
1503 var date_ = YUD.getAttribute(node.firstElementChild,'date');
1493 return date_
1504 return date_
1494 }
1505 }
1495
1506
1496 var get_age = function(node){
1507 var get_age = function(node){
1497 return node
1508 return node
1498 }
1509 }
1499
1510
1500 var get_link = function(node){
1511 var get_link = function(node){
1501 return node.firstElementChild.text;
1512 return node.firstElementChild.text;
1502 }
1513 }
1503
1514
1504 var revisionSort = function(a, b, desc, field) {
1515 var revisionSort = function(a, b, desc, field) {
1505
1516
1506 var a_ = fromHTML(a.getData(field));
1517 var a_ = fromHTML(a.getData(field));
1507 var b_ = fromHTML(b.getData(field));
1518 var b_ = fromHTML(b.getData(field));
1508
1519
1509 // extract revisions from string nodes
1520 // extract revisions from string nodes
1510 a_ = get_rev(a_)
1521 a_ = get_rev(a_)
1511 b_ = get_rev(b_)
1522 b_ = get_rev(b_)
1512
1523
1513 var comp = YAHOO.util.Sort.compare;
1524 var comp = YAHOO.util.Sort.compare;
1514 var compState = comp(a_, b_, desc);
1525 var compState = comp(a_, b_, desc);
1515 return compState;
1526 return compState;
1516 };
1527 };
1517 var ageSort = function(a, b, desc, field) {
1528 var ageSort = function(a, b, desc, field) {
1518 var a_ = fromHTML(a.getData(field));
1529 var a_ = fromHTML(a.getData(field));
1519 var b_ = fromHTML(b.getData(field));
1530 var b_ = fromHTML(b.getData(field));
1520
1531
1521 // extract name from table
1532 // extract name from table
1522 a_ = get_date(a_)
1533 a_ = get_date(a_)
1523 b_ = get_date(b_)
1534 b_ = get_date(b_)
1524
1535
1525 var comp = YAHOO.util.Sort.compare;
1536 var comp = YAHOO.util.Sort.compare;
1526 var compState = comp(a_, b_, desc);
1537 var compState = comp(a_, b_, desc);
1527 return compState;
1538 return compState;
1528 };
1539 };
1529
1540
1530 var lastLoginSort = function(a, b, desc, field) {
1541 var lastLoginSort = function(a, b, desc, field) {
1531 var a_ = a.getData('last_login_raw') || 0;
1542 var a_ = a.getData('last_login_raw') || 0;
1532 var b_ = b.getData('last_login_raw') || 0;
1543 var b_ = b.getData('last_login_raw') || 0;
1533
1544
1534 var comp = YAHOO.util.Sort.compare;
1545 var comp = YAHOO.util.Sort.compare;
1535 var compState = comp(a_, b_, desc);
1546 var compState = comp(a_, b_, desc);
1536 return compState;
1547 return compState;
1537 };
1548 };
1538
1549
1539 var nameSort = function(a, b, desc, field) {
1550 var nameSort = function(a, b, desc, field) {
1540 var a_ = fromHTML(a.getData(field));
1551 var a_ = fromHTML(a.getData(field));
1541 var b_ = fromHTML(b.getData(field));
1552 var b_ = fromHTML(b.getData(field));
1542
1553
1543 // extract name from table
1554 // extract name from table
1544 a_ = get_name(a_)
1555 a_ = get_name(a_)
1545 b_ = get_name(b_)
1556 b_ = get_name(b_)
1546
1557
1547 var comp = YAHOO.util.Sort.compare;
1558 var comp = YAHOO.util.Sort.compare;
1548 var compState = comp(a_, b_, desc);
1559 var compState = comp(a_, b_, desc);
1549 return compState;
1560 return compState;
1550 };
1561 };
1551
1562
1552 var permNameSort = function(a, b, desc, field) {
1563 var permNameSort = function(a, b, desc, field) {
1553 var a_ = fromHTML(a.getData(field));
1564 var a_ = fromHTML(a.getData(field));
1554 var b_ = fromHTML(b.getData(field));
1565 var b_ = fromHTML(b.getData(field));
1555 // extract name from table
1566 // extract name from table
1556
1567
1557 a_ = a_.children[0].innerHTML;
1568 a_ = a_.children[0].innerHTML;
1558 b_ = b_.children[0].innerHTML;
1569 b_ = b_.children[0].innerHTML;
1559
1570
1560 var comp = YAHOO.util.Sort.compare;
1571 var comp = YAHOO.util.Sort.compare;
1561 var compState = comp(a_, b_, desc);
1572 var compState = comp(a_, b_, desc);
1562 return compState;
1573 return compState;
1563 };
1574 };
1564
1575
1565 var groupNameSort = function(a, b, desc, field) {
1576 var groupNameSort = function(a, b, desc, field) {
1566 var a_ = fromHTML(a.getData(field));
1577 var a_ = fromHTML(a.getData(field));
1567 var b_ = fromHTML(b.getData(field));
1578 var b_ = fromHTML(b.getData(field));
1568
1579
1569 // extract name from table
1580 // extract name from table
1570 a_ = get_group_name(a_)
1581 a_ = get_group_name(a_)
1571 b_ = get_group_name(b_)
1582 b_ = get_group_name(b_)
1572
1583
1573 var comp = YAHOO.util.Sort.compare;
1584 var comp = YAHOO.util.Sort.compare;
1574 var compState = comp(a_, b_, desc);
1585 var compState = comp(a_, b_, desc);
1575 return compState;
1586 return compState;
1576 };
1587 };
1577 var dateSort = function(a, b, desc, field) {
1588 var dateSort = function(a, b, desc, field) {
1578 var a_ = fromHTML(a.getData(field));
1589 var a_ = fromHTML(a.getData(field));
1579 var b_ = fromHTML(b.getData(field));
1590 var b_ = fromHTML(b.getData(field));
1580
1591
1581 // extract name from table
1592 // extract name from table
1582 a_ = get_date(a_)
1593 a_ = get_date(a_)
1583 b_ = get_date(b_)
1594 b_ = get_date(b_)
1584
1595
1585 var comp = YAHOO.util.Sort.compare;
1596 var comp = YAHOO.util.Sort.compare;
1586 var compState = comp(a_, b_, desc);
1597 var compState = comp(a_, b_, desc);
1587 return compState;
1598 return compState;
1588 };
1599 };
1589
1600
1590 var linkSort = function(a, b, desc, field) {
1601 var linkSort = function(a, b, desc, field) {
1591 var a_ = fromHTML(a.getData(field));
1602 var a_ = fromHTML(a.getData(field));
1592 var b_ = fromHTML(a.getData(field));
1603 var b_ = fromHTML(a.getData(field));
1593
1604
1594 // extract url text from string nodes
1605 // extract url text from string nodes
1595 a_ = get_link(a_)
1606 a_ = get_link(a_)
1596 b_ = get_link(b_)
1607 b_ = get_link(b_)
1597
1608
1598 var comp = YAHOO.util.Sort.compare;
1609 var comp = YAHOO.util.Sort.compare;
1599 var compState = comp(a_, b_, desc);
1610 var compState = comp(a_, b_, desc);
1600 return compState;
1611 return compState;
1601 }
1612 }
1602
1613
1603 var addPermAction = function(_html, users_list, groups_list){
1614 var addPermAction = function(_html, users_list, groups_list){
1604 var elmts = YUD.getElementsByClassName('last_new_member');
1615 var elmts = YUD.getElementsByClassName('last_new_member');
1605 var last_node = elmts[elmts.length-1];
1616 var last_node = elmts[elmts.length-1];
1606 if (last_node){
1617 if (last_node){
1607 var next_id = (YUD.getElementsByClassName('new_members')).length;
1618 var next_id = (YUD.getElementsByClassName('new_members')).length;
1608 _html = _html.format(next_id);
1619 _html = _html.format(next_id);
1609 last_node.innerHTML = _html;
1620 last_node.innerHTML = _html;
1610 YUD.setStyle(last_node, 'display', '');
1621 YUD.setStyle(last_node, 'display', '');
1611 YUD.removeClass(last_node, 'last_new_member');
1622 YUD.removeClass(last_node, 'last_new_member');
1612 MembersAutoComplete("perm_new_member_name_"+next_id,
1623 MembersAutoComplete("perm_new_member_name_"+next_id,
1613 "perm_container_"+next_id, users_list, groups_list);
1624 "perm_container_"+next_id, users_list, groups_list);
1614 //create new last NODE
1625 //create new last NODE
1615 var el = document.createElement('tr');
1626 var el = document.createElement('tr');
1616 el.id = 'add_perm_input';
1627 el.id = 'add_perm_input';
1617 YUD.addClass(el,'last_new_member');
1628 YUD.addClass(el,'last_new_member');
1618 YUD.addClass(el,'new_members');
1629 YUD.addClass(el,'new_members');
1619 YUD.insertAfter(el, last_node);
1630 YUD.insertAfter(el, last_node);
1620 }
1631 }
1621 }
1632 }
1622
1633
1623 /* Multi selectors */
1634 /* Multi selectors */
1624
1635
1625 var MultiSelectWidget = function(selected_id, available_id, form_id){
1636 var MultiSelectWidget = function(selected_id, available_id, form_id){
1626
1637
1627
1638
1628 //definition of containers ID's
1639 //definition of containers ID's
1629 var selected_container = selected_id;
1640 var selected_container = selected_id;
1630 var available_container = available_id;
1641 var available_container = available_id;
1631
1642
1632 //temp container for selected storage.
1643 //temp container for selected storage.
1633 var cache = new Array();
1644 var cache = new Array();
1634 var av_cache = new Array();
1645 var av_cache = new Array();
1635 var c = YUD.get(selected_container);
1646 var c = YUD.get(selected_container);
1636 var ac = YUD.get(available_container);
1647 var ac = YUD.get(available_container);
1637
1648
1638 //get only selected options for further fullfilment
1649 //get only selected options for further fullfilment
1639 for(var i = 0;node =c.options[i];i++){
1650 for(var i = 0;node =c.options[i];i++){
1640 if(node.selected){
1651 if(node.selected){
1641 //push selected to my temp storage left overs :)
1652 //push selected to my temp storage left overs :)
1642 cache.push(node);
1653 cache.push(node);
1643 }
1654 }
1644 }
1655 }
1645
1656
1646 //get all available options to cache
1657 //get all available options to cache
1647 for(var i = 0;node =ac.options[i];i++){
1658 for(var i = 0;node =ac.options[i];i++){
1648 //push selected to my temp storage left overs :)
1659 //push selected to my temp storage left overs :)
1649 av_cache.push(node);
1660 av_cache.push(node);
1650 }
1661 }
1651
1662
1652 //fill available only with those not in choosen
1663 //fill available only with those not in choosen
1653 ac.options.length=0;
1664 ac.options.length=0;
1654 tmp_cache = new Array();
1665 tmp_cache = new Array();
1655
1666
1656 for(var i = 0;node = av_cache[i];i++){
1667 for(var i = 0;node = av_cache[i];i++){
1657 var add = true;
1668 var add = true;
1658 for(var i2 = 0;node_2 = cache[i2];i2++){
1669 for(var i2 = 0;node_2 = cache[i2];i2++){
1659 if(node.value == node_2.value){
1670 if(node.value == node_2.value){
1660 add=false;
1671 add=false;
1661 break;
1672 break;
1662 }
1673 }
1663 }
1674 }
1664 if(add){
1675 if(add){
1665 tmp_cache.push(new Option(node.text, node.value, false, false));
1676 tmp_cache.push(new Option(node.text, node.value, false, false));
1666 }
1677 }
1667 }
1678 }
1668
1679
1669 for(var i = 0;node = tmp_cache[i];i++){
1680 for(var i = 0;node = tmp_cache[i];i++){
1670 ac.options[i] = node;
1681 ac.options[i] = node;
1671 }
1682 }
1672
1683
1673 function prompts_action_callback(e){
1684 function prompts_action_callback(e){
1674
1685
1675 var choosen = YUD.get(selected_container);
1686 var choosen = YUD.get(selected_container);
1676 var available = YUD.get(available_container);
1687 var available = YUD.get(available_container);
1677
1688
1678 //get checked and unchecked options from field
1689 //get checked and unchecked options from field
1679 function get_checked(from_field){
1690 function get_checked(from_field){
1680 //temp container for storage.
1691 //temp container for storage.
1681 var sel_cache = new Array();
1692 var sel_cache = new Array();
1682 var oth_cache = new Array();
1693 var oth_cache = new Array();
1683
1694
1684 for(var i = 0;node = from_field.options[i];i++){
1695 for(var i = 0;node = from_field.options[i];i++){
1685 if(node.selected){
1696 if(node.selected){
1686 //push selected fields :)
1697 //push selected fields :)
1687 sel_cache.push(node);
1698 sel_cache.push(node);
1688 }
1699 }
1689 else{
1700 else{
1690 oth_cache.push(node)
1701 oth_cache.push(node)
1691 }
1702 }
1692 }
1703 }
1693
1704
1694 return [sel_cache,oth_cache]
1705 return [sel_cache,oth_cache]
1695 }
1706 }
1696
1707
1697 //fill the field with given options
1708 //fill the field with given options
1698 function fill_with(field,options){
1709 function fill_with(field,options){
1699 //clear firtst
1710 //clear firtst
1700 field.options.length=0;
1711 field.options.length=0;
1701 for(var i = 0;node = options[i];i++){
1712 for(var i = 0;node = options[i];i++){
1702 field.options[i]=new Option(node.text, node.value,
1713 field.options[i]=new Option(node.text, node.value,
1703 false, false);
1714 false, false);
1704 }
1715 }
1705
1716
1706 }
1717 }
1707 //adds to current field
1718 //adds to current field
1708 function add_to(field,options){
1719 function add_to(field,options){
1709 for(var i = 0;node = options[i];i++){
1720 for(var i = 0;node = options[i];i++){
1710 field.appendChild(new Option(node.text, node.value,
1721 field.appendChild(new Option(node.text, node.value,
1711 false, false));
1722 false, false));
1712 }
1723 }
1713 }
1724 }
1714
1725
1715 // add action
1726 // add action
1716 if (this.id=='add_element'){
1727 if (this.id=='add_element'){
1717 var c = get_checked(available);
1728 var c = get_checked(available);
1718 add_to(choosen,c[0]);
1729 add_to(choosen,c[0]);
1719 fill_with(available,c[1]);
1730 fill_with(available,c[1]);
1720 }
1731 }
1721 // remove action
1732 // remove action
1722 if (this.id=='remove_element'){
1733 if (this.id=='remove_element'){
1723 var c = get_checked(choosen);
1734 var c = get_checked(choosen);
1724 add_to(available,c[0]);
1735 add_to(available,c[0]);
1725 fill_with(choosen,c[1]);
1736 fill_with(choosen,c[1]);
1726 }
1737 }
1727 // add all elements
1738 // add all elements
1728 if(this.id=='add_all_elements'){
1739 if(this.id=='add_all_elements'){
1729 for(var i=0; node = available.options[i];i++){
1740 for(var i=0; node = available.options[i];i++){
1730 choosen.appendChild(new Option(node.text,
1741 choosen.appendChild(new Option(node.text,
1731 node.value, false, false));
1742 node.value, false, false));
1732 }
1743 }
1733 available.options.length = 0;
1744 available.options.length = 0;
1734 }
1745 }
1735 //remove all elements
1746 //remove all elements
1736 if(this.id=='remove_all_elements'){
1747 if(this.id=='remove_all_elements'){
1737 for(var i=0; node = choosen.options[i];i++){
1748 for(var i=0; node = choosen.options[i];i++){
1738 available.appendChild(new Option(node.text,
1749 available.appendChild(new Option(node.text,
1739 node.value, false, false));
1750 node.value, false, false));
1740 }
1751 }
1741 choosen.options.length = 0;
1752 choosen.options.length = 0;
1742 }
1753 }
1743
1754
1744 }
1755 }
1745
1756
1746 YUE.addListener(['add_element','remove_element',
1757 YUE.addListener(['add_element','remove_element',
1747 'add_all_elements','remove_all_elements'],'click',
1758 'add_all_elements','remove_all_elements'],'click',
1748 prompts_action_callback)
1759 prompts_action_callback)
1749 if (form_id !== undefined) {
1760 if (form_id !== undefined) {
1750 YUE.addListener(form_id,'submit',function(){
1761 YUE.addListener(form_id,'submit',function(){
1751 var choosen = YUD.get(selected_container);
1762 var choosen = YUD.get(selected_container);
1752 for (var i = 0; i < choosen.options.length; i++) {
1763 for (var i = 0; i < choosen.options.length; i++) {
1753 choosen.options[i].selected = 'selected';
1764 choosen.options[i].selected = 'selected';
1754 }
1765 }
1755 });
1766 });
1756 }
1767 }
1757 }
1768 }
@@ -1,196 +1,202 b''
1 <%inherit file="/base/base.html"/>
1 <%inherit file="/base/base.html"/>
2
2
3 <%def name="title()">
3 <%def name="title()">
4 ${c.repo_name} ${_('New pull request')}
4 ${c.repo_name} ${_('New pull request')}
5 </%def>
5 </%def>
6
6
7 <%def name="breadcrumbs_links()">
7 <%def name="breadcrumbs_links()">
8 ${h.link_to(_(u'Home'),h.url('/'))}
8 ${h.link_to(_(u'Home'),h.url('/'))}
9 &raquo;
9 &raquo;
10 ${h.link_to(c.repo_name,h.url('changelog_home',repo_name=c.repo_name))}
10 ${h.link_to(c.repo_name,h.url('changelog_home',repo_name=c.repo_name))}
11 &raquo;
11 &raquo;
12 ${_('New pull request')}
12 ${_('New pull request')}
13 </%def>
13 </%def>
14
14
15 <%def name="main()">
15 <%def name="main()">
16
16
17 <div class="box">
17 <div class="box">
18 <!-- box / title -->
18 <!-- box / title -->
19 <div class="title">
19 <div class="title">
20 ${self.breadcrumbs()}
20 ${self.breadcrumbs()}
21 </div>
21 </div>
22 ${h.form(url('pullrequest', repo_name=c.repo_name), method='post', id='pull_request_form')}
22 ${h.form(url('pullrequest', repo_name=c.repo_name), method='post', id='pull_request_form')}
23 <div style="float:left;padding:0px 30px 30px 30px">
23 <div style="float:left;padding:0px 30px 30px 30px">
24 <div style="padding:0px 5px 5px 5px">
24 <div style="padding:0px 5px 5px 5px">
25 <span>
25 <span>
26 <a id="refresh" href="#">
26 <a id="refresh" href="#">
27 <img class="icon" title="${_('Refresh')}" alt="${_('Refresh')}" src="${h.url('/images/icons/arrow_refresh.png')}"/>
27 <img class="icon" title="${_('Refresh')}" alt="${_('Refresh')}" src="${h.url('/images/icons/arrow_refresh.png')}"/>
28 ${_('refresh overview')}
28 ${_('refresh overview')}
29 </a>
29 </a>
30 </span>
30 </span>
31 </div>
31 </div>
32 ##ORG
32 ##ORG
33 <div style="float:left">
33 <div style="float:left">
34 <div class="fork_user">
34 <div class="fork_user">
35 <div class="gravatar">
35 <div class="gravatar">
36 <img alt="gravatar" src="${h.gravatar_url(c.rhodecode_db_repo.user.email,24)}"/>
36 <img alt="gravatar" src="${h.gravatar_url(c.rhodecode_db_repo.user.email,24)}"/>
37 </div>
37 </div>
38 <span style="font-size: 20px">
38 <span style="font-size: 20px">
39 ${h.select('org_repo','',c.org_repos,class_='refs')}:${h.select('org_ref','',c.org_refs,class_='refs')}
39 ${h.select('org_repo','',c.org_repos,class_='refs')}:${h.select('org_ref','',c.org_refs,class_='refs')}
40 </span>
40 </span>
41 <div style="padding:5px 3px 3px 42px;">${c.rhodecode_db_repo.description}</div>
41 <div style="padding:5px 3px 3px 42px;">${c.rhodecode_db_repo.description}</div>
42 </div>
42 </div>
43 <div style="clear:both;padding-top: 10px"></div>
43 <div style="clear:both;padding-top: 10px"></div>
44 </div>
44 </div>
45 <div style="float:left;font-size:24px;padding:0px 20px">
45 <div style="float:left;font-size:24px;padding:0px 20px">
46 <img height=32 width=32 src="${h.url('/images/arrow_right_64.png')}"/>
46 <img height=32 width=32 src="${h.url('/images/arrow_right_64.png')}"/>
47 </div>
47 </div>
48
48
49 ##OTHER, most Probably the PARENT OF THIS FORK
49 ##OTHER, most Probably the PARENT OF THIS FORK
50 <div style="float:left">
50 <div style="float:left">
51 <div class="fork_user">
51 <div class="fork_user">
52 <div class="gravatar">
52 <div class="gravatar">
53 <img id="other_repo_gravatar" alt="gravatar" src=""/>
53 <img id="other_repo_gravatar" alt="gravatar" src=""/>
54 </div>
54 </div>
55 <span style="font-size: 20px">
55 <span style="font-size: 20px">
56 ${h.select('other_repo',c.default_pull_request ,c.other_repos,class_='refs')}:${h.select('other_ref','',c.default_revs,class_='refs')}
56 ${h.select('other_repo',c.default_pull_request ,c.other_repos,class_='refs')}:${h.select('other_ref',c.default_pull_request_rev,c.default_revs,class_='refs')}
57 </span>
57 </span>
58 <div id="other_repo_desc" style="padding:5px 3px 3px 42px;"></div>
58 <div id="other_repo_desc" style="padding:5px 3px 3px 42px;"></div>
59 </div>
59 </div>
60 <div style="clear:both;padding-top: 10px"></div>
60 <div style="clear:both;padding-top: 10px"></div>
61 </div>
61 </div>
62 <div style="clear:both;padding-top: 10px"></div>
62 <div style="clear:both;padding-top: 10px"></div>
63 ## overview pulled by ajax
63 ## overview pulled by ajax
64 <div style="float:left" id="pull_request_overview"></div>
64 <div style="float:left" id="pull_request_overview"></div>
65 <div style="float:left;clear:both;padding:10px 10px 10px 0px;display:none">
65 <div style="float:left;clear:both;padding:10px 10px 10px 0px;display:none">
66 <a id="pull_request_overview_url" href="#">${_('Detailed compare view')}</a>
66 <a id="pull_request_overview_url" href="#">${_('Detailed compare view')}</a>
67 </div>
67 </div>
68 </div>
68 </div>
69 <div style="float:left; border-left:1px dashed #eee">
69 <div style="float:left; border-left:1px dashed #eee">
70 <h4>${_('Pull request reviewers')}</h4>
70 <h4>${_('Pull request reviewers')}</h4>
71 <div id="reviewers" style="padding:0px 0px 0px 15px">
71 <div id="reviewers" style="padding:0px 0px 0px 15px">
72 ## members goes here !
72 ## members goes here !
73 <div class="group_members_wrap">
73 <div class="group_members_wrap">
74 <ul id="review_members" class="group_members">
74 <ul id="review_members" class="group_members">
75 %for member in c.review_members:
75 %for member in c.review_members:
76 <li id="reviewer_${member.user_id}">
76 <li id="reviewer_${member.user_id}">
77 <div class="reviewers_member">
77 <div class="reviewers_member">
78 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(member.email,14)}"/> </div>
78 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(member.email,14)}"/> </div>
79 <div style="float:left">${member.full_name} (${_('owner')})</div>
79 <div style="float:left">${member.full_name} (${_('owner')})</div>
80 <input type="hidden" value="${member.user_id}" name="review_members" />
80 <input type="hidden" value="${member.user_id}" name="review_members" />
81 <span class="delete_icon action_button" onclick="removeReviewer(${member.user_id})"></span>
81 <span class="delete_icon action_button" onclick="removeReviewer(${member.user_id})"></span>
82 </div>
82 </div>
83 </li>
83 </li>
84 %endfor
84 %endfor
85 </ul>
85 </ul>
86 </div>
86 </div>
87
87
88 <div class='ac'>
88 <div class='ac'>
89 <div class="reviewer_ac">
89 <div class="reviewer_ac">
90 ${h.text('user', class_='yui-ac-input')}
90 ${h.text('user', class_='yui-ac-input')}
91 <span class="help-block">${_('Add reviewer to this pull request.')}</span>
91 <span class="help-block">${_('Add reviewer to this pull request.')}</span>
92 <div id="reviewers_container"></div>
92 <div id="reviewers_container"></div>
93 </div>
93 </div>
94 </div>
94 </div>
95 </div>
95 </div>
96 </div>
96 </div>
97 <h3>${_('Create new pull request')}</h3>
97 <h3>${_('Create new pull request')}</h3>
98
98
99 <div class="form">
99 <div class="form">
100 <!-- fields -->
100 <!-- fields -->
101
101
102 <div class="fields">
102 <div class="fields">
103
103
104 <div class="field">
104 <div class="field">
105 <div class="label">
105 <div class="label">
106 <label for="pullrequest_title">${_('Title')}:</label>
106 <label for="pullrequest_title">${_('Title')}:</label>
107 </div>
107 </div>
108 <div class="input">
108 <div class="input">
109 ${h.text('pullrequest_title',size=30)}
109 ${h.text('pullrequest_title',size=30)}
110 </div>
110 </div>
111 </div>
111 </div>
112
112
113 <div class="field">
113 <div class="field">
114 <div class="label label-textarea">
114 <div class="label label-textarea">
115 <label for="pullrequest_desc">${_('description')}:</label>
115 <label for="pullrequest_desc">${_('description')}:</label>
116 </div>
116 </div>
117 <div class="textarea text-area editor">
117 <div class="textarea text-area editor">
118 ${h.textarea('pullrequest_desc',size=30)}
118 ${h.textarea('pullrequest_desc',size=30)}
119 </div>
119 </div>
120 </div>
120 </div>
121
121
122 <div class="buttons">
122 <div class="buttons">
123 ${h.submit('save',_('Send pull request'),class_="ui-btn large")}
123 ${h.submit('save',_('Send pull request'),class_="ui-btn large")}
124 ${h.reset('reset',_('Reset'),class_="ui-btn large")}
124 ${h.reset('reset',_('Reset'),class_="ui-btn large")}
125 </div>
125 </div>
126 </div>
126 </div>
127 </div>
127 </div>
128 ${h.end_form()}
128 ${h.end_form()}
129
129
130 </div>
130 </div>
131
131
132 <script type="text/javascript">
132 <script type="text/javascript">
133 var _USERS_AC_DATA = ${c.users_array|n};
133 var _USERS_AC_DATA = ${c.users_array|n};
134 var _GROUPS_AC_DATA = ${c.users_groups_array|n};
134 var _GROUPS_AC_DATA = ${c.users_groups_array|n};
135 PullRequestAutoComplete('user', 'reviewers_container', _USERS_AC_DATA, _GROUPS_AC_DATA);
135 PullRequestAutoComplete('user', 'reviewers_container', _USERS_AC_DATA, _GROUPS_AC_DATA);
136
136
137 var other_repos_info = ${c.other_repos_info|n};
137 var other_repos_info = ${c.other_repos_info|n};
138
138
139 var loadPreview = function(){
139 var loadPreview = function(){
140 YUD.setStyle(YUD.get('pull_request_overview_url').parentElement,'display','none');
140 YUD.setStyle(YUD.get('pull_request_overview_url').parentElement,'display','none');
141 var url = "${h.url('compare_url',
141 var url = "${h.url('compare_url',
142 repo_name='org_repo',
142 repo_name='org_repo',
143 org_ref_type='org_ref_type', org_ref='org_ref',
143 org_ref_type='org_ref_type', org_ref='org_ref',
144 other_ref_type='other_ref_type', other_ref='other_ref',
144 other_ref_type='other_ref_type', other_ref='other_ref',
145 repo='other_repo',
145 repo='other_repo',
146 as_form=True)}";
146 as_form=True)}";
147
147
148 var select_refs = YUQ('#pull_request_form select.refs')
148 var select_refs = YUQ('#pull_request_form select.refs')
149
149 var rev_data = {}; // gather the org/other ref and repo here
150 for(var i=0;i<select_refs.length;i++){
150 for(var i=0;i<select_refs.length;i++){
151 var select_ref = select_refs[i];
151 var select_ref = select_refs[i];
152 var select_ref_data = select_ref.value.split(':');
152 var select_ref_data = select_ref.value.split(':');
153 var key = null;
153 var key = null;
154 var val = null;
154 var val = null;
155
155 if(select_ref_data.length>1){
156 if(select_ref_data.length>1){
156 key = select_ref.name+"_type";
157 key = select_ref.name+"_type";
157 val = select_ref_data[0];
158 val = select_ref_data[0];
158 url = url.replace(key,val);
159 url = url.replace(key,val);
160 rev_data[key] = val;
159
161
160 key = select_ref.name;
162 key = select_ref.name;
161 val = select_ref_data[1];
163 val = select_ref_data[1];
162 url = url.replace(key,val);
164 url = url.replace(key,val);
165 rev_data[key] = val;
163
166
164 }else{
167 }else{
165 key = select_ref.name;
168 key = select_ref.name;
166 val = select_ref.value;
169 val = select_ref.value;
167 url = url.replace(key,val);
170 url = url.replace(key,val);
171 rev_data[key] = val;
168 }
172 }
169 }
173 }
170
174
171 YUE.on('other_repo', 'change', function(e){
175 YUE.on('other_repo', 'change', function(e){
172 var repo_name = e.currentTarget.value;
176 var repo_name = e.currentTarget.value;
173 // replace the <select> of changed repo
177 // replace the <select> of changed repo
174 YUD.get('other_ref').innerHTML = other_repos_info[repo_name]['revs'];
178 YUD.get('other_ref').innerHTML = other_repos_info[repo_name]['revs'];
175 });
179 });
176
180
177 ypjax(url,'pull_request_overview', function(data){
181 ypjax(url,'pull_request_overview', function(data){
178 var sel_box = YUQ('#pull_request_form #other_repo')[0];
182 var sel_box = YUQ('#pull_request_form #other_repo')[0];
179 var repo_name = sel_box.options[sel_box.selectedIndex].value;
183 var repo_name = sel_box.options[sel_box.selectedIndex].value;
180 YUD.get('pull_request_overview_url').href = url;
184 YUD.get('pull_request_overview_url').href = url;
181 YUD.setStyle(YUD.get('pull_request_overview_url').parentElement,'display','');
185 YUD.setStyle(YUD.get('pull_request_overview_url').parentElement,'display','');
182 YUD.get('other_repo_gravatar').src = other_repos_info[repo_name]['gravatar'];
186 YUD.get('other_repo_gravatar').src = other_repos_info[repo_name]['gravatar'];
183 YUD.get('other_repo_desc').innerHTML = other_repos_info[repo_name]['description'];
187 YUD.get('other_repo_desc').innerHTML = other_repos_info[repo_name]['description'];
184 YUD.get('other_ref').innerHTML = other_repos_info[repo_name]['revs'];
188 YUD.get('other_ref').innerHTML = other_repos_info[repo_name]['revs'];
189 // select back the revision that was just compared
190 setSelectValue(YUD.get('other_ref'), rev_data['other_ref']);
185 })
191 })
186 }
192 }
187 YUE.on('refresh','click',function(e){
193 YUE.on('refresh','click',function(e){
188 loadPreview()
194 loadPreview()
189 })
195 })
190
196
191 //lazy load overview after 0.5s
197 //lazy load overview after 0.5s
192 setTimeout(loadPreview, 500)
198 setTimeout(loadPreview, 500)
193
199
194 </script>
200 </script>
195
201
196 </%def>
202 </%def>
General Comments 0
You need to be logged in to leave comments. Login now