##// END OF EJS Templates
Enabled inline comments in pull-requests
marcink -
r2489:a0adf8db beta
parent child Browse files
Show More
@@ -1,558 +1,563 b''
1 """
1 """
2 Routes configuration
2 Routes configuration
3
3
4 The more specific and detailed routes should be defined first so they
4 The more specific and detailed routes should be defined first so they
5 may take precedent over the more generic routes. For more information
5 may take precedent over the more generic routes. For more information
6 refer to the routes manual at http://routes.groovie.org/docs/
6 refer to the routes manual at http://routes.groovie.org/docs/
7 """
7 """
8 from __future__ import with_statement
8 from __future__ import with_statement
9 from routes import Mapper
9 from routes import Mapper
10
10
11 # prefix for non repository related links needs to be prefixed with `/`
11 # prefix for non repository related links needs to be prefixed with `/`
12 ADMIN_PREFIX = '/_admin'
12 ADMIN_PREFIX = '/_admin'
13
13
14
14
15 def make_map(config):
15 def make_map(config):
16 """Create, configure and return the routes Mapper"""
16 """Create, configure and return the routes Mapper"""
17 rmap = Mapper(directory=config['pylons.paths']['controllers'],
17 rmap = Mapper(directory=config['pylons.paths']['controllers'],
18 always_scan=config['debug'])
18 always_scan=config['debug'])
19 rmap.minimization = False
19 rmap.minimization = False
20 rmap.explicit = False
20 rmap.explicit = False
21
21
22 from rhodecode.lib.utils import is_valid_repo
22 from rhodecode.lib.utils import is_valid_repo
23 from rhodecode.lib.utils import is_valid_repos_group
23 from rhodecode.lib.utils import is_valid_repos_group
24
24
25 def check_repo(environ, match_dict):
25 def check_repo(environ, match_dict):
26 """
26 """
27 check for valid repository for proper 404 handling
27 check for valid repository for proper 404 handling
28
28
29 :param environ:
29 :param environ:
30 :param match_dict:
30 :param match_dict:
31 """
31 """
32 from rhodecode.model.db import Repository
32 from rhodecode.model.db import Repository
33 repo_name = match_dict.get('repo_name')
33 repo_name = match_dict.get('repo_name')
34
34
35 try:
35 try:
36 by_id = repo_name.split('_')
36 by_id = repo_name.split('_')
37 if len(by_id) == 2 and by_id[1].isdigit():
37 if len(by_id) == 2 and by_id[1].isdigit():
38 repo_name = Repository.get(by_id[1]).repo_name
38 repo_name = Repository.get(by_id[1]).repo_name
39 match_dict['repo_name'] = repo_name
39 match_dict['repo_name'] = repo_name
40 except:
40 except:
41 pass
41 pass
42
42
43 return is_valid_repo(repo_name, config['base_path'])
43 return is_valid_repo(repo_name, config['base_path'])
44
44
45 def check_group(environ, match_dict):
45 def check_group(environ, match_dict):
46 """
46 """
47 check for valid repositories group for proper 404 handling
47 check for valid repositories group for proper 404 handling
48
48
49 :param environ:
49 :param environ:
50 :param match_dict:
50 :param match_dict:
51 """
51 """
52 repos_group_name = match_dict.get('group_name')
52 repos_group_name = match_dict.get('group_name')
53
53
54 return is_valid_repos_group(repos_group_name, config['base_path'])
54 return is_valid_repos_group(repos_group_name, config['base_path'])
55
55
56 def check_int(environ, match_dict):
56 def check_int(environ, match_dict):
57 return match_dict.get('id').isdigit()
57 return match_dict.get('id').isdigit()
58
58
59 # The ErrorController route (handles 404/500 error pages); it should
59 # The ErrorController route (handles 404/500 error pages); it should
60 # likely stay at the top, ensuring it can always be resolved
60 # likely stay at the top, ensuring it can always be resolved
61 rmap.connect('/error/{action}', controller='error')
61 rmap.connect('/error/{action}', controller='error')
62 rmap.connect('/error/{action}/{id}', controller='error')
62 rmap.connect('/error/{action}/{id}', controller='error')
63
63
64 #==========================================================================
64 #==========================================================================
65 # CUSTOM ROUTES HERE
65 # CUSTOM ROUTES HERE
66 #==========================================================================
66 #==========================================================================
67
67
68 #MAIN PAGE
68 #MAIN PAGE
69 rmap.connect('home', '/', controller='home', action='index')
69 rmap.connect('home', '/', controller='home', action='index')
70 rmap.connect('repo_switcher', '/repos', controller='home',
70 rmap.connect('repo_switcher', '/repos', controller='home',
71 action='repo_switcher')
71 action='repo_switcher')
72 rmap.connect('branch_tag_switcher', '/branches-tags/{repo_name:.*}',
72 rmap.connect('branch_tag_switcher', '/branches-tags/{repo_name:.*}',
73 controller='home', action='branch_tag_switcher')
73 controller='home', action='branch_tag_switcher')
74 rmap.connect('bugtracker',
74 rmap.connect('bugtracker',
75 "http://bitbucket.org/marcinkuzminski/rhodecode/issues",
75 "http://bitbucket.org/marcinkuzminski/rhodecode/issues",
76 _static=True)
76 _static=True)
77 rmap.connect('rst_help',
77 rmap.connect('rst_help',
78 "http://docutils.sourceforge.net/docs/user/rst/quickref.html",
78 "http://docutils.sourceforge.net/docs/user/rst/quickref.html",
79 _static=True)
79 _static=True)
80 rmap.connect('rhodecode_official', "http://rhodecode.org", _static=True)
80 rmap.connect('rhodecode_official', "http://rhodecode.org", _static=True)
81
81
82 #ADMIN REPOSITORY REST ROUTES
82 #ADMIN REPOSITORY REST ROUTES
83 with rmap.submapper(path_prefix=ADMIN_PREFIX,
83 with rmap.submapper(path_prefix=ADMIN_PREFIX,
84 controller='admin/repos') as m:
84 controller='admin/repos') as m:
85 m.connect("repos", "/repos",
85 m.connect("repos", "/repos",
86 action="create", conditions=dict(method=["POST"]))
86 action="create", conditions=dict(method=["POST"]))
87 m.connect("repos", "/repos",
87 m.connect("repos", "/repos",
88 action="index", conditions=dict(method=["GET"]))
88 action="index", conditions=dict(method=["GET"]))
89 m.connect("formatted_repos", "/repos.{format}",
89 m.connect("formatted_repos", "/repos.{format}",
90 action="index",
90 action="index",
91 conditions=dict(method=["GET"]))
91 conditions=dict(method=["GET"]))
92 m.connect("new_repo", "/repos/new",
92 m.connect("new_repo", "/repos/new",
93 action="new", conditions=dict(method=["GET"]))
93 action="new", conditions=dict(method=["GET"]))
94 m.connect("formatted_new_repo", "/repos/new.{format}",
94 m.connect("formatted_new_repo", "/repos/new.{format}",
95 action="new", conditions=dict(method=["GET"]))
95 action="new", conditions=dict(method=["GET"]))
96 m.connect("/repos/{repo_name:.*}",
96 m.connect("/repos/{repo_name:.*}",
97 action="update", conditions=dict(method=["PUT"],
97 action="update", conditions=dict(method=["PUT"],
98 function=check_repo))
98 function=check_repo))
99 m.connect("/repos/{repo_name:.*}",
99 m.connect("/repos/{repo_name:.*}",
100 action="delete", conditions=dict(method=["DELETE"],
100 action="delete", conditions=dict(method=["DELETE"],
101 function=check_repo))
101 function=check_repo))
102 m.connect("edit_repo", "/repos/{repo_name:.*}/edit",
102 m.connect("edit_repo", "/repos/{repo_name:.*}/edit",
103 action="edit", conditions=dict(method=["GET"],
103 action="edit", conditions=dict(method=["GET"],
104 function=check_repo))
104 function=check_repo))
105 m.connect("formatted_edit_repo", "/repos/{repo_name:.*}.{format}/edit",
105 m.connect("formatted_edit_repo", "/repos/{repo_name:.*}.{format}/edit",
106 action="edit", conditions=dict(method=["GET"],
106 action="edit", conditions=dict(method=["GET"],
107 function=check_repo))
107 function=check_repo))
108 m.connect("repo", "/repos/{repo_name:.*}",
108 m.connect("repo", "/repos/{repo_name:.*}",
109 action="show", conditions=dict(method=["GET"],
109 action="show", conditions=dict(method=["GET"],
110 function=check_repo))
110 function=check_repo))
111 m.connect("formatted_repo", "/repos/{repo_name:.*}.{format}",
111 m.connect("formatted_repo", "/repos/{repo_name:.*}.{format}",
112 action="show", conditions=dict(method=["GET"],
112 action="show", conditions=dict(method=["GET"],
113 function=check_repo))
113 function=check_repo))
114 #ajax delete repo perm user
114 #ajax delete repo perm user
115 m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
115 m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
116 action="delete_perm_user",
116 action="delete_perm_user",
117 conditions=dict(method=["DELETE"], function=check_repo))
117 conditions=dict(method=["DELETE"], function=check_repo))
118
118
119 #ajax delete repo perm users_group
119 #ajax delete repo perm users_group
120 m.connect('delete_repo_users_group',
120 m.connect('delete_repo_users_group',
121 "/repos_delete_users_group/{repo_name:.*}",
121 "/repos_delete_users_group/{repo_name:.*}",
122 action="delete_perm_users_group",
122 action="delete_perm_users_group",
123 conditions=dict(method=["DELETE"], function=check_repo))
123 conditions=dict(method=["DELETE"], function=check_repo))
124
124
125 #settings actions
125 #settings actions
126 m.connect('repo_stats', "/repos_stats/{repo_name:.*}",
126 m.connect('repo_stats', "/repos_stats/{repo_name:.*}",
127 action="repo_stats", conditions=dict(method=["DELETE"],
127 action="repo_stats", conditions=dict(method=["DELETE"],
128 function=check_repo))
128 function=check_repo))
129 m.connect('repo_cache', "/repos_cache/{repo_name:.*}",
129 m.connect('repo_cache', "/repos_cache/{repo_name:.*}",
130 action="repo_cache", conditions=dict(method=["DELETE"],
130 action="repo_cache", conditions=dict(method=["DELETE"],
131 function=check_repo))
131 function=check_repo))
132 m.connect('repo_public_journal', "/repos_public_journal/{repo_name:.*}",
132 m.connect('repo_public_journal', "/repos_public_journal/{repo_name:.*}",
133 action="repo_public_journal", conditions=dict(method=["PUT"],
133 action="repo_public_journal", conditions=dict(method=["PUT"],
134 function=check_repo))
134 function=check_repo))
135 m.connect('repo_pull', "/repo_pull/{repo_name:.*}",
135 m.connect('repo_pull', "/repo_pull/{repo_name:.*}",
136 action="repo_pull", conditions=dict(method=["PUT"],
136 action="repo_pull", conditions=dict(method=["PUT"],
137 function=check_repo))
137 function=check_repo))
138 m.connect('repo_as_fork', "/repo_as_fork/{repo_name:.*}",
138 m.connect('repo_as_fork', "/repo_as_fork/{repo_name:.*}",
139 action="repo_as_fork", conditions=dict(method=["PUT"],
139 action="repo_as_fork", conditions=dict(method=["PUT"],
140 function=check_repo))
140 function=check_repo))
141
141
142 with rmap.submapper(path_prefix=ADMIN_PREFIX,
142 with rmap.submapper(path_prefix=ADMIN_PREFIX,
143 controller='admin/repos_groups') as m:
143 controller='admin/repos_groups') as m:
144 m.connect("repos_groups", "/repos_groups",
144 m.connect("repos_groups", "/repos_groups",
145 action="create", conditions=dict(method=["POST"]))
145 action="create", conditions=dict(method=["POST"]))
146 m.connect("repos_groups", "/repos_groups",
146 m.connect("repos_groups", "/repos_groups",
147 action="index", conditions=dict(method=["GET"]))
147 action="index", conditions=dict(method=["GET"]))
148 m.connect("formatted_repos_groups", "/repos_groups.{format}",
148 m.connect("formatted_repos_groups", "/repos_groups.{format}",
149 action="index", conditions=dict(method=["GET"]))
149 action="index", conditions=dict(method=["GET"]))
150 m.connect("new_repos_group", "/repos_groups/new",
150 m.connect("new_repos_group", "/repos_groups/new",
151 action="new", conditions=dict(method=["GET"]))
151 action="new", conditions=dict(method=["GET"]))
152 m.connect("formatted_new_repos_group", "/repos_groups/new.{format}",
152 m.connect("formatted_new_repos_group", "/repos_groups/new.{format}",
153 action="new", conditions=dict(method=["GET"]))
153 action="new", conditions=dict(method=["GET"]))
154 m.connect("update_repos_group", "/repos_groups/{id}",
154 m.connect("update_repos_group", "/repos_groups/{id}",
155 action="update", conditions=dict(method=["PUT"],
155 action="update", conditions=dict(method=["PUT"],
156 function=check_int))
156 function=check_int))
157 m.connect("delete_repos_group", "/repos_groups/{id}",
157 m.connect("delete_repos_group", "/repos_groups/{id}",
158 action="delete", conditions=dict(method=["DELETE"],
158 action="delete", conditions=dict(method=["DELETE"],
159 function=check_int))
159 function=check_int))
160 m.connect("edit_repos_group", "/repos_groups/{id}/edit",
160 m.connect("edit_repos_group", "/repos_groups/{id}/edit",
161 action="edit", conditions=dict(method=["GET"],
161 action="edit", conditions=dict(method=["GET"],
162 function=check_int))
162 function=check_int))
163 m.connect("formatted_edit_repos_group",
163 m.connect("formatted_edit_repos_group",
164 "/repos_groups/{id}.{format}/edit",
164 "/repos_groups/{id}.{format}/edit",
165 action="edit", conditions=dict(method=["GET"],
165 action="edit", conditions=dict(method=["GET"],
166 function=check_int))
166 function=check_int))
167 m.connect("repos_group", "/repos_groups/{id}",
167 m.connect("repos_group", "/repos_groups/{id}",
168 action="show", conditions=dict(method=["GET"],
168 action="show", conditions=dict(method=["GET"],
169 function=check_int))
169 function=check_int))
170 m.connect("formatted_repos_group", "/repos_groups/{id}.{format}",
170 m.connect("formatted_repos_group", "/repos_groups/{id}.{format}",
171 action="show", conditions=dict(method=["GET"],
171 action="show", conditions=dict(method=["GET"],
172 function=check_int))
172 function=check_int))
173 # ajax delete repos group perm user
173 # ajax delete repos group perm user
174 m.connect('delete_repos_group_user_perm',
174 m.connect('delete_repos_group_user_perm',
175 "/delete_repos_group_user_perm/{group_name:.*}",
175 "/delete_repos_group_user_perm/{group_name:.*}",
176 action="delete_repos_group_user_perm",
176 action="delete_repos_group_user_perm",
177 conditions=dict(method=["DELETE"], function=check_group))
177 conditions=dict(method=["DELETE"], function=check_group))
178
178
179 # ajax delete repos group perm users_group
179 # ajax delete repos group perm users_group
180 m.connect('delete_repos_group_users_group_perm',
180 m.connect('delete_repos_group_users_group_perm',
181 "/delete_repos_group_users_group_perm/{group_name:.*}",
181 "/delete_repos_group_users_group_perm/{group_name:.*}",
182 action="delete_repos_group_users_group_perm",
182 action="delete_repos_group_users_group_perm",
183 conditions=dict(method=["DELETE"], function=check_group))
183 conditions=dict(method=["DELETE"], function=check_group))
184
184
185 #ADMIN USER REST ROUTES
185 #ADMIN USER REST ROUTES
186 with rmap.submapper(path_prefix=ADMIN_PREFIX,
186 with rmap.submapper(path_prefix=ADMIN_PREFIX,
187 controller='admin/users') as m:
187 controller='admin/users') as m:
188 m.connect("users", "/users",
188 m.connect("users", "/users",
189 action="create", conditions=dict(method=["POST"]))
189 action="create", conditions=dict(method=["POST"]))
190 m.connect("users", "/users",
190 m.connect("users", "/users",
191 action="index", conditions=dict(method=["GET"]))
191 action="index", conditions=dict(method=["GET"]))
192 m.connect("formatted_users", "/users.{format}",
192 m.connect("formatted_users", "/users.{format}",
193 action="index", conditions=dict(method=["GET"]))
193 action="index", conditions=dict(method=["GET"]))
194 m.connect("new_user", "/users/new",
194 m.connect("new_user", "/users/new",
195 action="new", conditions=dict(method=["GET"]))
195 action="new", conditions=dict(method=["GET"]))
196 m.connect("formatted_new_user", "/users/new.{format}",
196 m.connect("formatted_new_user", "/users/new.{format}",
197 action="new", conditions=dict(method=["GET"]))
197 action="new", conditions=dict(method=["GET"]))
198 m.connect("update_user", "/users/{id}",
198 m.connect("update_user", "/users/{id}",
199 action="update", conditions=dict(method=["PUT"]))
199 action="update", conditions=dict(method=["PUT"]))
200 m.connect("delete_user", "/users/{id}",
200 m.connect("delete_user", "/users/{id}",
201 action="delete", conditions=dict(method=["DELETE"]))
201 action="delete", conditions=dict(method=["DELETE"]))
202 m.connect("edit_user", "/users/{id}/edit",
202 m.connect("edit_user", "/users/{id}/edit",
203 action="edit", conditions=dict(method=["GET"]))
203 action="edit", conditions=dict(method=["GET"]))
204 m.connect("formatted_edit_user",
204 m.connect("formatted_edit_user",
205 "/users/{id}.{format}/edit",
205 "/users/{id}.{format}/edit",
206 action="edit", conditions=dict(method=["GET"]))
206 action="edit", conditions=dict(method=["GET"]))
207 m.connect("user", "/users/{id}",
207 m.connect("user", "/users/{id}",
208 action="show", conditions=dict(method=["GET"]))
208 action="show", conditions=dict(method=["GET"]))
209 m.connect("formatted_user", "/users/{id}.{format}",
209 m.connect("formatted_user", "/users/{id}.{format}",
210 action="show", conditions=dict(method=["GET"]))
210 action="show", conditions=dict(method=["GET"]))
211
211
212 #EXTRAS USER ROUTES
212 #EXTRAS USER ROUTES
213 m.connect("user_perm", "/users_perm/{id}",
213 m.connect("user_perm", "/users_perm/{id}",
214 action="update_perm", conditions=dict(method=["PUT"]))
214 action="update_perm", conditions=dict(method=["PUT"]))
215 m.connect("user_emails", "/users_emails/{id}",
215 m.connect("user_emails", "/users_emails/{id}",
216 action="add_email", conditions=dict(method=["PUT"]))
216 action="add_email", conditions=dict(method=["PUT"]))
217 m.connect("user_emails_delete", "/users_emails/{id}",
217 m.connect("user_emails_delete", "/users_emails/{id}",
218 action="delete_email", conditions=dict(method=["DELETE"]))
218 action="delete_email", conditions=dict(method=["DELETE"]))
219
219
220 #ADMIN USERS GROUPS REST ROUTES
220 #ADMIN USERS GROUPS REST ROUTES
221 with rmap.submapper(path_prefix=ADMIN_PREFIX,
221 with rmap.submapper(path_prefix=ADMIN_PREFIX,
222 controller='admin/users_groups') as m:
222 controller='admin/users_groups') as m:
223 m.connect("users_groups", "/users_groups",
223 m.connect("users_groups", "/users_groups",
224 action="create", conditions=dict(method=["POST"]))
224 action="create", conditions=dict(method=["POST"]))
225 m.connect("users_groups", "/users_groups",
225 m.connect("users_groups", "/users_groups",
226 action="index", conditions=dict(method=["GET"]))
226 action="index", conditions=dict(method=["GET"]))
227 m.connect("formatted_users_groups", "/users_groups.{format}",
227 m.connect("formatted_users_groups", "/users_groups.{format}",
228 action="index", conditions=dict(method=["GET"]))
228 action="index", conditions=dict(method=["GET"]))
229 m.connect("new_users_group", "/users_groups/new",
229 m.connect("new_users_group", "/users_groups/new",
230 action="new", conditions=dict(method=["GET"]))
230 action="new", conditions=dict(method=["GET"]))
231 m.connect("formatted_new_users_group", "/users_groups/new.{format}",
231 m.connect("formatted_new_users_group", "/users_groups/new.{format}",
232 action="new", conditions=dict(method=["GET"]))
232 action="new", conditions=dict(method=["GET"]))
233 m.connect("update_users_group", "/users_groups/{id}",
233 m.connect("update_users_group", "/users_groups/{id}",
234 action="update", conditions=dict(method=["PUT"]))
234 action="update", conditions=dict(method=["PUT"]))
235 m.connect("delete_users_group", "/users_groups/{id}",
235 m.connect("delete_users_group", "/users_groups/{id}",
236 action="delete", conditions=dict(method=["DELETE"]))
236 action="delete", conditions=dict(method=["DELETE"]))
237 m.connect("edit_users_group", "/users_groups/{id}/edit",
237 m.connect("edit_users_group", "/users_groups/{id}/edit",
238 action="edit", conditions=dict(method=["GET"]))
238 action="edit", conditions=dict(method=["GET"]))
239 m.connect("formatted_edit_users_group",
239 m.connect("formatted_edit_users_group",
240 "/users_groups/{id}.{format}/edit",
240 "/users_groups/{id}.{format}/edit",
241 action="edit", conditions=dict(method=["GET"]))
241 action="edit", conditions=dict(method=["GET"]))
242 m.connect("users_group", "/users_groups/{id}",
242 m.connect("users_group", "/users_groups/{id}",
243 action="show", conditions=dict(method=["GET"]))
243 action="show", conditions=dict(method=["GET"]))
244 m.connect("formatted_users_group", "/users_groups/{id}.{format}",
244 m.connect("formatted_users_group", "/users_groups/{id}.{format}",
245 action="show", conditions=dict(method=["GET"]))
245 action="show", conditions=dict(method=["GET"]))
246
246
247 #EXTRAS USER ROUTES
247 #EXTRAS USER ROUTES
248 m.connect("users_group_perm", "/users_groups_perm/{id}",
248 m.connect("users_group_perm", "/users_groups_perm/{id}",
249 action="update_perm", conditions=dict(method=["PUT"]))
249 action="update_perm", conditions=dict(method=["PUT"]))
250
250
251 #ADMIN GROUP REST ROUTES
251 #ADMIN GROUP REST ROUTES
252 rmap.resource('group', 'groups',
252 rmap.resource('group', 'groups',
253 controller='admin/groups', path_prefix=ADMIN_PREFIX)
253 controller='admin/groups', path_prefix=ADMIN_PREFIX)
254
254
255 #ADMIN PERMISSIONS REST ROUTES
255 #ADMIN PERMISSIONS REST ROUTES
256 rmap.resource('permission', 'permissions',
256 rmap.resource('permission', 'permissions',
257 controller='admin/permissions', path_prefix=ADMIN_PREFIX)
257 controller='admin/permissions', path_prefix=ADMIN_PREFIX)
258
258
259 ##ADMIN LDAP SETTINGS
259 ##ADMIN LDAP SETTINGS
260 rmap.connect('ldap_settings', '%s/ldap' % ADMIN_PREFIX,
260 rmap.connect('ldap_settings', '%s/ldap' % ADMIN_PREFIX,
261 controller='admin/ldap_settings', action='ldap_settings',
261 controller='admin/ldap_settings', action='ldap_settings',
262 conditions=dict(method=["POST"]))
262 conditions=dict(method=["POST"]))
263
263
264 rmap.connect('ldap_home', '%s/ldap' % ADMIN_PREFIX,
264 rmap.connect('ldap_home', '%s/ldap' % ADMIN_PREFIX,
265 controller='admin/ldap_settings')
265 controller='admin/ldap_settings')
266
266
267 #ADMIN SETTINGS REST ROUTES
267 #ADMIN SETTINGS REST ROUTES
268 with rmap.submapper(path_prefix=ADMIN_PREFIX,
268 with rmap.submapper(path_prefix=ADMIN_PREFIX,
269 controller='admin/settings') as m:
269 controller='admin/settings') as m:
270 m.connect("admin_settings", "/settings",
270 m.connect("admin_settings", "/settings",
271 action="create", conditions=dict(method=["POST"]))
271 action="create", conditions=dict(method=["POST"]))
272 m.connect("admin_settings", "/settings",
272 m.connect("admin_settings", "/settings",
273 action="index", conditions=dict(method=["GET"]))
273 action="index", conditions=dict(method=["GET"]))
274 m.connect("formatted_admin_settings", "/settings.{format}",
274 m.connect("formatted_admin_settings", "/settings.{format}",
275 action="index", conditions=dict(method=["GET"]))
275 action="index", conditions=dict(method=["GET"]))
276 m.connect("admin_new_setting", "/settings/new",
276 m.connect("admin_new_setting", "/settings/new",
277 action="new", conditions=dict(method=["GET"]))
277 action="new", conditions=dict(method=["GET"]))
278 m.connect("formatted_admin_new_setting", "/settings/new.{format}",
278 m.connect("formatted_admin_new_setting", "/settings/new.{format}",
279 action="new", conditions=dict(method=["GET"]))
279 action="new", conditions=dict(method=["GET"]))
280 m.connect("/settings/{setting_id}",
280 m.connect("/settings/{setting_id}",
281 action="update", conditions=dict(method=["PUT"]))
281 action="update", conditions=dict(method=["PUT"]))
282 m.connect("/settings/{setting_id}",
282 m.connect("/settings/{setting_id}",
283 action="delete", conditions=dict(method=["DELETE"]))
283 action="delete", conditions=dict(method=["DELETE"]))
284 m.connect("admin_edit_setting", "/settings/{setting_id}/edit",
284 m.connect("admin_edit_setting", "/settings/{setting_id}/edit",
285 action="edit", conditions=dict(method=["GET"]))
285 action="edit", conditions=dict(method=["GET"]))
286 m.connect("formatted_admin_edit_setting",
286 m.connect("formatted_admin_edit_setting",
287 "/settings/{setting_id}.{format}/edit",
287 "/settings/{setting_id}.{format}/edit",
288 action="edit", conditions=dict(method=["GET"]))
288 action="edit", conditions=dict(method=["GET"]))
289 m.connect("admin_setting", "/settings/{setting_id}",
289 m.connect("admin_setting", "/settings/{setting_id}",
290 action="show", conditions=dict(method=["GET"]))
290 action="show", conditions=dict(method=["GET"]))
291 m.connect("formatted_admin_setting", "/settings/{setting_id}.{format}",
291 m.connect("formatted_admin_setting", "/settings/{setting_id}.{format}",
292 action="show", conditions=dict(method=["GET"]))
292 action="show", conditions=dict(method=["GET"]))
293 m.connect("admin_settings_my_account", "/my_account",
293 m.connect("admin_settings_my_account", "/my_account",
294 action="my_account", conditions=dict(method=["GET"]))
294 action="my_account", conditions=dict(method=["GET"]))
295 m.connect("admin_settings_my_account_update", "/my_account_update",
295 m.connect("admin_settings_my_account_update", "/my_account_update",
296 action="my_account_update", conditions=dict(method=["PUT"]))
296 action="my_account_update", conditions=dict(method=["PUT"]))
297 m.connect("admin_settings_create_repository", "/create_repository",
297 m.connect("admin_settings_create_repository", "/create_repository",
298 action="create_repository", conditions=dict(method=["GET"]))
298 action="create_repository", conditions=dict(method=["GET"]))
299
299
300 #NOTIFICATION REST ROUTES
300 #NOTIFICATION REST ROUTES
301 with rmap.submapper(path_prefix=ADMIN_PREFIX,
301 with rmap.submapper(path_prefix=ADMIN_PREFIX,
302 controller='admin/notifications') as m:
302 controller='admin/notifications') as m:
303 m.connect("notifications", "/notifications",
303 m.connect("notifications", "/notifications",
304 action="create", conditions=dict(method=["POST"]))
304 action="create", conditions=dict(method=["POST"]))
305 m.connect("notifications", "/notifications",
305 m.connect("notifications", "/notifications",
306 action="index", conditions=dict(method=["GET"]))
306 action="index", conditions=dict(method=["GET"]))
307 m.connect("notifications_mark_all_read", "/notifications/mark_all_read",
307 m.connect("notifications_mark_all_read", "/notifications/mark_all_read",
308 action="mark_all_read", conditions=dict(method=["GET"]))
308 action="mark_all_read", conditions=dict(method=["GET"]))
309 m.connect("formatted_notifications", "/notifications.{format}",
309 m.connect("formatted_notifications", "/notifications.{format}",
310 action="index", conditions=dict(method=["GET"]))
310 action="index", conditions=dict(method=["GET"]))
311 m.connect("new_notification", "/notifications/new",
311 m.connect("new_notification", "/notifications/new",
312 action="new", conditions=dict(method=["GET"]))
312 action="new", conditions=dict(method=["GET"]))
313 m.connect("formatted_new_notification", "/notifications/new.{format}",
313 m.connect("formatted_new_notification", "/notifications/new.{format}",
314 action="new", conditions=dict(method=["GET"]))
314 action="new", conditions=dict(method=["GET"]))
315 m.connect("/notification/{notification_id}",
315 m.connect("/notification/{notification_id}",
316 action="update", conditions=dict(method=["PUT"]))
316 action="update", conditions=dict(method=["PUT"]))
317 m.connect("/notification/{notification_id}",
317 m.connect("/notification/{notification_id}",
318 action="delete", conditions=dict(method=["DELETE"]))
318 action="delete", conditions=dict(method=["DELETE"]))
319 m.connect("edit_notification", "/notification/{notification_id}/edit",
319 m.connect("edit_notification", "/notification/{notification_id}/edit",
320 action="edit", conditions=dict(method=["GET"]))
320 action="edit", conditions=dict(method=["GET"]))
321 m.connect("formatted_edit_notification",
321 m.connect("formatted_edit_notification",
322 "/notification/{notification_id}.{format}/edit",
322 "/notification/{notification_id}.{format}/edit",
323 action="edit", conditions=dict(method=["GET"]))
323 action="edit", conditions=dict(method=["GET"]))
324 m.connect("notification", "/notification/{notification_id}",
324 m.connect("notification", "/notification/{notification_id}",
325 action="show", conditions=dict(method=["GET"]))
325 action="show", conditions=dict(method=["GET"]))
326 m.connect("formatted_notification", "/notifications/{notification_id}.{format}",
326 m.connect("formatted_notification", "/notifications/{notification_id}.{format}",
327 action="show", conditions=dict(method=["GET"]))
327 action="show", conditions=dict(method=["GET"]))
328
328
329 #ADMIN MAIN PAGES
329 #ADMIN MAIN PAGES
330 with rmap.submapper(path_prefix=ADMIN_PREFIX,
330 with rmap.submapper(path_prefix=ADMIN_PREFIX,
331 controller='admin/admin') as m:
331 controller='admin/admin') as m:
332 m.connect('admin_home', '', action='index')
332 m.connect('admin_home', '', action='index')
333 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
333 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
334 action='add_repo')
334 action='add_repo')
335
335
336 #==========================================================================
336 #==========================================================================
337 # API V2
337 # API V2
338 #==========================================================================
338 #==========================================================================
339 with rmap.submapper(path_prefix=ADMIN_PREFIX,
339 with rmap.submapper(path_prefix=ADMIN_PREFIX,
340 controller='api/api') as m:
340 controller='api/api') as m:
341 m.connect('api', '/api')
341 m.connect('api', '/api')
342
342
343 #USER JOURNAL
343 #USER JOURNAL
344 rmap.connect('journal', '%s/journal' % ADMIN_PREFIX,
344 rmap.connect('journal', '%s/journal' % ADMIN_PREFIX,
345 controller='journal', action='index')
345 controller='journal', action='index')
346 rmap.connect('journal_rss', '%s/journal/rss' % ADMIN_PREFIX,
346 rmap.connect('journal_rss', '%s/journal/rss' % ADMIN_PREFIX,
347 controller='journal', action='journal_rss')
347 controller='journal', action='journal_rss')
348 rmap.connect('journal_atom', '%s/journal/atom' % ADMIN_PREFIX,
348 rmap.connect('journal_atom', '%s/journal/atom' % ADMIN_PREFIX,
349 controller='journal', action='journal_atom')
349 controller='journal', action='journal_atom')
350
350
351 rmap.connect('public_journal', '%s/public_journal' % ADMIN_PREFIX,
351 rmap.connect('public_journal', '%s/public_journal' % ADMIN_PREFIX,
352 controller='journal', action="public_journal")
352 controller='journal', action="public_journal")
353
353
354 rmap.connect('public_journal_rss', '%s/public_journal/rss' % ADMIN_PREFIX,
354 rmap.connect('public_journal_rss', '%s/public_journal/rss' % ADMIN_PREFIX,
355 controller='journal', action="public_journal_rss")
355 controller='journal', action="public_journal_rss")
356
356
357 rmap.connect('public_journal_rss_old', '%s/public_journal_rss' % ADMIN_PREFIX,
357 rmap.connect('public_journal_rss_old', '%s/public_journal_rss' % ADMIN_PREFIX,
358 controller='journal', action="public_journal_rss")
358 controller='journal', action="public_journal_rss")
359
359
360 rmap.connect('public_journal_atom',
360 rmap.connect('public_journal_atom',
361 '%s/public_journal/atom' % ADMIN_PREFIX, controller='journal',
361 '%s/public_journal/atom' % ADMIN_PREFIX, controller='journal',
362 action="public_journal_atom")
362 action="public_journal_atom")
363
363
364 rmap.connect('public_journal_atom_old',
364 rmap.connect('public_journal_atom_old',
365 '%s/public_journal_atom' % ADMIN_PREFIX, controller='journal',
365 '%s/public_journal_atom' % ADMIN_PREFIX, controller='journal',
366 action="public_journal_atom")
366 action="public_journal_atom")
367
367
368 rmap.connect('toggle_following', '%s/toggle_following' % ADMIN_PREFIX,
368 rmap.connect('toggle_following', '%s/toggle_following' % ADMIN_PREFIX,
369 controller='journal', action='toggle_following',
369 controller='journal', action='toggle_following',
370 conditions=dict(method=["POST"]))
370 conditions=dict(method=["POST"]))
371
371
372 #SEARCH
372 #SEARCH
373 rmap.connect('search', '%s/search' % ADMIN_PREFIX, controller='search',)
373 rmap.connect('search', '%s/search' % ADMIN_PREFIX, controller='search',)
374 rmap.connect('search_repo', '%s/search/{search_repo:.*}' % ADMIN_PREFIX,
374 rmap.connect('search_repo', '%s/search/{search_repo:.*}' % ADMIN_PREFIX,
375 controller='search')
375 controller='search')
376
376
377 #LOGIN/LOGOUT/REGISTER/SIGN IN
377 #LOGIN/LOGOUT/REGISTER/SIGN IN
378 rmap.connect('login_home', '%s/login' % ADMIN_PREFIX, controller='login')
378 rmap.connect('login_home', '%s/login' % ADMIN_PREFIX, controller='login')
379 rmap.connect('logout_home', '%s/logout' % ADMIN_PREFIX, controller='login',
379 rmap.connect('logout_home', '%s/logout' % ADMIN_PREFIX, controller='login',
380 action='logout')
380 action='logout')
381
381
382 rmap.connect('register', '%s/register' % ADMIN_PREFIX, controller='login',
382 rmap.connect('register', '%s/register' % ADMIN_PREFIX, controller='login',
383 action='register')
383 action='register')
384
384
385 rmap.connect('reset_password', '%s/password_reset' % ADMIN_PREFIX,
385 rmap.connect('reset_password', '%s/password_reset' % ADMIN_PREFIX,
386 controller='login', action='password_reset')
386 controller='login', action='password_reset')
387
387
388 rmap.connect('reset_password_confirmation',
388 rmap.connect('reset_password_confirmation',
389 '%s/password_reset_confirmation' % ADMIN_PREFIX,
389 '%s/password_reset_confirmation' % ADMIN_PREFIX,
390 controller='login', action='password_reset_confirmation')
390 controller='login', action='password_reset_confirmation')
391
391
392 #FEEDS
392 #FEEDS
393 rmap.connect('rss_feed_home', '/{repo_name:.*}/feed/rss',
393 rmap.connect('rss_feed_home', '/{repo_name:.*}/feed/rss',
394 controller='feed', action='rss',
394 controller='feed', action='rss',
395 conditions=dict(function=check_repo))
395 conditions=dict(function=check_repo))
396
396
397 rmap.connect('atom_feed_home', '/{repo_name:.*}/feed/atom',
397 rmap.connect('atom_feed_home', '/{repo_name:.*}/feed/atom',
398 controller='feed', action='atom',
398 controller='feed', action='atom',
399 conditions=dict(function=check_repo))
399 conditions=dict(function=check_repo))
400
400
401 #==========================================================================
401 #==========================================================================
402 # REPOSITORY ROUTES
402 # REPOSITORY ROUTES
403 #==========================================================================
403 #==========================================================================
404 rmap.connect('summary_home', '/{repo_name:.*}',
404 rmap.connect('summary_home', '/{repo_name:.*}',
405 controller='summary',
405 controller='summary',
406 conditions=dict(function=check_repo))
406 conditions=dict(function=check_repo))
407
407
408 rmap.connect('repos_group_home', '/{group_name:.*}',
408 rmap.connect('repos_group_home', '/{group_name:.*}',
409 controller='admin/repos_groups', action="show_by_name",
409 controller='admin/repos_groups', action="show_by_name",
410 conditions=dict(function=check_group))
410 conditions=dict(function=check_group))
411
411
412 rmap.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
412 rmap.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
413 controller='changeset', revision='tip',
413 controller='changeset', revision='tip',
414 conditions=dict(function=check_repo))
414 conditions=dict(function=check_repo))
415
415
416 rmap.connect('changeset_comment',
416 rmap.connect('changeset_comment',
417 '/{repo_name:.*}/changeset/{revision}/comment',
417 '/{repo_name:.*}/changeset/{revision}/comment',
418 controller='changeset', revision='tip', action='comment',
418 controller='changeset', revision='tip', action='comment',
419 conditions=dict(function=check_repo))
419 conditions=dict(function=check_repo))
420
420
421 rmap.connect('changeset_comment_delete',
421 rmap.connect('changeset_comment_delete',
422 '/{repo_name:.*}/changeset/comment/{comment_id}/delete',
422 '/{repo_name:.*}/changeset/comment/{comment_id}/delete',
423 controller='changeset', action='delete_comment',
423 controller='changeset', action='delete_comment',
424 conditions=dict(function=check_repo, method=["DELETE"]))
424 conditions=dict(function=check_repo, method=["DELETE"]))
425
425
426 rmap.connect('raw_changeset_home',
426 rmap.connect('raw_changeset_home',
427 '/{repo_name:.*}/raw-changeset/{revision}',
427 '/{repo_name:.*}/raw-changeset/{revision}',
428 controller='changeset', action='raw_changeset',
428 controller='changeset', action='raw_changeset',
429 revision='tip', conditions=dict(function=check_repo))
429 revision='tip', conditions=dict(function=check_repo))
430
430
431 rmap.connect('compare_url',
431 rmap.connect('compare_url',
432 '/{repo_name:.*}/compare/{org_ref_type}@{org_ref}...{other_ref_type}@{other_ref}',
432 '/{repo_name:.*}/compare/{org_ref_type}@{org_ref}...{other_ref_type}@{other_ref}',
433 controller='compare', action='index',
433 controller='compare', action='index',
434 conditions=dict(function=check_repo),
434 conditions=dict(function=check_repo),
435 requirements=dict(org_ref_type='(branch|book|tag)',
435 requirements=dict(org_ref_type='(branch|book|tag)',
436 other_ref_type='(branch|book|tag)'))
436 other_ref_type='(branch|book|tag)'))
437
437
438 rmap.connect('pullrequest_home',
438 rmap.connect('pullrequest_home',
439 '/{repo_name:.*}/pull-request/new', controller='pullrequests',
439 '/{repo_name:.*}/pull-request/new', controller='pullrequests',
440 action='index', conditions=dict(function=check_repo,
440 action='index', conditions=dict(function=check_repo,
441 method=["GET"]))
441 method=["GET"]))
442
442
443 rmap.connect('pullrequest',
443 rmap.connect('pullrequest',
444 '/{repo_name:.*}/pull-request/new', controller='pullrequests',
444 '/{repo_name:.*}/pull-request/new', controller='pullrequests',
445 action='create', conditions=dict(function=check_repo,
445 action='create', conditions=dict(function=check_repo,
446 method=["POST"]))
446 method=["POST"]))
447
447
448 rmap.connect('pullrequest_show',
448 rmap.connect('pullrequest_show',
449 '/{repo_name:.*}/pull-request/{pull_request_id}',
449 '/{repo_name:.*}/pull-request/{pull_request_id}',
450 controller='pullrequests',
450 controller='pullrequests',
451 action='show', conditions=dict(function=check_repo,
451 action='show', conditions=dict(function=check_repo,
452 method=["GET"]))
452 method=["GET"]))
453
453
454 rmap.connect('pullrequest_show_all',
454 rmap.connect('pullrequest_show_all',
455 '/{repo_name:.*}/pull-request',
455 '/{repo_name:.*}/pull-request',
456 controller='pullrequests',
456 controller='pullrequests',
457 action='show_all', conditions=dict(function=check_repo,
457 action='show_all', conditions=dict(function=check_repo,
458 method=["GET"]))
458 method=["GET"]))
459
459
460 rmap.connect('pullrequest_comment',
460 rmap.connect('pullrequest_comment',
461 '/{repo_name:.*}/pull-request-comment/{pull_request_id}',
461 '/{repo_name:.*}/pull-request-comment/{pull_request_id}',
462 controller='pullrequests',
462 controller='pullrequests',
463 action='comment', conditions=dict(function=check_repo,
463 action='comment', conditions=dict(function=check_repo,
464 method=["POST"]))
464 method=["POST"]))
465
465
466 rmap.connect('pullrequest_comment_delete',
467 '/{repo_name:.*}/pull-request-comment/{comment_id}/delete',
468 controller='pullrequests', action='delete_comment',
469 conditions=dict(function=check_repo, method=["DELETE"]))
470
466 rmap.connect('summary_home', '/{repo_name:.*}/summary',
471 rmap.connect('summary_home', '/{repo_name:.*}/summary',
467 controller='summary', conditions=dict(function=check_repo))
472 controller='summary', conditions=dict(function=check_repo))
468
473
469 rmap.connect('shortlog_home', '/{repo_name:.*}/shortlog',
474 rmap.connect('shortlog_home', '/{repo_name:.*}/shortlog',
470 controller='shortlog', conditions=dict(function=check_repo))
475 controller='shortlog', conditions=dict(function=check_repo))
471
476
472 rmap.connect('branches_home', '/{repo_name:.*}/branches',
477 rmap.connect('branches_home', '/{repo_name:.*}/branches',
473 controller='branches', conditions=dict(function=check_repo))
478 controller='branches', conditions=dict(function=check_repo))
474
479
475 rmap.connect('tags_home', '/{repo_name:.*}/tags',
480 rmap.connect('tags_home', '/{repo_name:.*}/tags',
476 controller='tags', conditions=dict(function=check_repo))
481 controller='tags', conditions=dict(function=check_repo))
477
482
478 rmap.connect('bookmarks_home', '/{repo_name:.*}/bookmarks',
483 rmap.connect('bookmarks_home', '/{repo_name:.*}/bookmarks',
479 controller='bookmarks', conditions=dict(function=check_repo))
484 controller='bookmarks', conditions=dict(function=check_repo))
480
485
481 rmap.connect('changelog_home', '/{repo_name:.*}/changelog',
486 rmap.connect('changelog_home', '/{repo_name:.*}/changelog',
482 controller='changelog', conditions=dict(function=check_repo))
487 controller='changelog', conditions=dict(function=check_repo))
483
488
484 rmap.connect('changelog_details', '/{repo_name:.*}/changelog_details/{cs}',
489 rmap.connect('changelog_details', '/{repo_name:.*}/changelog_details/{cs}',
485 controller='changelog', action='changelog_details',
490 controller='changelog', action='changelog_details',
486 conditions=dict(function=check_repo))
491 conditions=dict(function=check_repo))
487
492
488 rmap.connect('files_home', '/{repo_name:.*}/files/{revision}/{f_path:.*}',
493 rmap.connect('files_home', '/{repo_name:.*}/files/{revision}/{f_path:.*}',
489 controller='files', revision='tip', f_path='',
494 controller='files', revision='tip', f_path='',
490 conditions=dict(function=check_repo))
495 conditions=dict(function=check_repo))
491
496
492 rmap.connect('files_diff_home', '/{repo_name:.*}/diff/{f_path:.*}',
497 rmap.connect('files_diff_home', '/{repo_name:.*}/diff/{f_path:.*}',
493 controller='files', action='diff', revision='tip', f_path='',
498 controller='files', action='diff', revision='tip', f_path='',
494 conditions=dict(function=check_repo))
499 conditions=dict(function=check_repo))
495
500
496 rmap.connect('files_rawfile_home',
501 rmap.connect('files_rawfile_home',
497 '/{repo_name:.*}/rawfile/{revision}/{f_path:.*}',
502 '/{repo_name:.*}/rawfile/{revision}/{f_path:.*}',
498 controller='files', action='rawfile', revision='tip',
503 controller='files', action='rawfile', revision='tip',
499 f_path='', conditions=dict(function=check_repo))
504 f_path='', conditions=dict(function=check_repo))
500
505
501 rmap.connect('files_raw_home',
506 rmap.connect('files_raw_home',
502 '/{repo_name:.*}/raw/{revision}/{f_path:.*}',
507 '/{repo_name:.*}/raw/{revision}/{f_path:.*}',
503 controller='files', action='raw', revision='tip', f_path='',
508 controller='files', action='raw', revision='tip', f_path='',
504 conditions=dict(function=check_repo))
509 conditions=dict(function=check_repo))
505
510
506 rmap.connect('files_annotate_home',
511 rmap.connect('files_annotate_home',
507 '/{repo_name:.*}/annotate/{revision}/{f_path:.*}',
512 '/{repo_name:.*}/annotate/{revision}/{f_path:.*}',
508 controller='files', action='index', revision='tip',
513 controller='files', action='index', revision='tip',
509 f_path='', annotate=True, conditions=dict(function=check_repo))
514 f_path='', annotate=True, conditions=dict(function=check_repo))
510
515
511 rmap.connect('files_edit_home',
516 rmap.connect('files_edit_home',
512 '/{repo_name:.*}/edit/{revision}/{f_path:.*}',
517 '/{repo_name:.*}/edit/{revision}/{f_path:.*}',
513 controller='files', action='edit', revision='tip',
518 controller='files', action='edit', revision='tip',
514 f_path='', conditions=dict(function=check_repo))
519 f_path='', conditions=dict(function=check_repo))
515
520
516 rmap.connect('files_add_home',
521 rmap.connect('files_add_home',
517 '/{repo_name:.*}/add/{revision}/{f_path:.*}',
522 '/{repo_name:.*}/add/{revision}/{f_path:.*}',
518 controller='files', action='add', revision='tip',
523 controller='files', action='add', revision='tip',
519 f_path='', conditions=dict(function=check_repo))
524 f_path='', conditions=dict(function=check_repo))
520
525
521 rmap.connect('files_archive_home', '/{repo_name:.*}/archive/{fname}',
526 rmap.connect('files_archive_home', '/{repo_name:.*}/archive/{fname}',
522 controller='files', action='archivefile',
527 controller='files', action='archivefile',
523 conditions=dict(function=check_repo))
528 conditions=dict(function=check_repo))
524
529
525 rmap.connect('files_nodelist_home',
530 rmap.connect('files_nodelist_home',
526 '/{repo_name:.*}/nodelist/{revision}/{f_path:.*}',
531 '/{repo_name:.*}/nodelist/{revision}/{f_path:.*}',
527 controller='files', action='nodelist',
532 controller='files', action='nodelist',
528 conditions=dict(function=check_repo))
533 conditions=dict(function=check_repo))
529
534
530 rmap.connect('repo_settings_delete', '/{repo_name:.*}/settings',
535 rmap.connect('repo_settings_delete', '/{repo_name:.*}/settings',
531 controller='settings', action="delete",
536 controller='settings', action="delete",
532 conditions=dict(method=["DELETE"], function=check_repo))
537 conditions=dict(method=["DELETE"], function=check_repo))
533
538
534 rmap.connect('repo_settings_update', '/{repo_name:.*}/settings',
539 rmap.connect('repo_settings_update', '/{repo_name:.*}/settings',
535 controller='settings', action="update",
540 controller='settings', action="update",
536 conditions=dict(method=["PUT"], function=check_repo))
541 conditions=dict(method=["PUT"], function=check_repo))
537
542
538 rmap.connect('repo_settings_home', '/{repo_name:.*}/settings',
543 rmap.connect('repo_settings_home', '/{repo_name:.*}/settings',
539 controller='settings', action='index',
544 controller='settings', action='index',
540 conditions=dict(function=check_repo))
545 conditions=dict(function=check_repo))
541
546
542 rmap.connect('repo_fork_create_home', '/{repo_name:.*}/fork',
547 rmap.connect('repo_fork_create_home', '/{repo_name:.*}/fork',
543 controller='forks', action='fork_create',
548 controller='forks', action='fork_create',
544 conditions=dict(function=check_repo, method=["POST"]))
549 conditions=dict(function=check_repo, method=["POST"]))
545
550
546 rmap.connect('repo_fork_home', '/{repo_name:.*}/fork',
551 rmap.connect('repo_fork_home', '/{repo_name:.*}/fork',
547 controller='forks', action='fork',
552 controller='forks', action='fork',
548 conditions=dict(function=check_repo))
553 conditions=dict(function=check_repo))
549
554
550 rmap.connect('repo_forks_home', '/{repo_name:.*}/forks',
555 rmap.connect('repo_forks_home', '/{repo_name:.*}/forks',
551 controller='forks', action='forks',
556 controller='forks', action='forks',
552 conditions=dict(function=check_repo))
557 conditions=dict(function=check_repo))
553
558
554 rmap.connect('repo_followers_home', '/{repo_name:.*}/followers',
559 rmap.connect('repo_followers_home', '/{repo_name:.*}/followers',
555 controller='followers', action='followers',
560 controller='followers', action='followers',
556 conditions=dict(function=check_repo))
561 conditions=dict(function=check_repo))
557
562
558 return rmap
563 return rmap
@@ -1,297 +1,310 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
27
28 from webob.exc import HTTPNotFound
28 from webob.exc import HTTPNotFound, HTTPForbidden
29 from collections import defaultdict
29 from collections import defaultdict
30 from itertools import groupby
30 from itertools import groupby
31
31
32 from pylons import request, response, session, tmpl_context as c, url
32 from pylons import request, response, session, tmpl_context as c, url
33 from pylons.controllers.util import abort, redirect
33 from pylons.controllers.util import abort, redirect
34 from pylons.i18n.translation import _
34 from pylons.i18n.translation import _
35 from pylons.decorators import jsonify
35 from pylons.decorators import jsonify
36
36
37 from rhodecode.lib.base import BaseRepoController, render
37 from rhodecode.lib.base import BaseRepoController, render
38 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
38 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
39 from rhodecode.lib import helpers as h
39 from rhodecode.lib import helpers as h
40 from rhodecode.lib import diffs
40 from rhodecode.lib import diffs
41 from rhodecode.lib.utils import action_logger
41 from rhodecode.lib.utils import action_logger
42 from rhodecode.model.db import User, PullRequest, ChangesetStatus
42 from rhodecode.model.db import User, PullRequest, ChangesetStatus,\
43 ChangesetComment
43 from rhodecode.model.pull_request import PullRequestModel
44 from rhodecode.model.pull_request import PullRequestModel
44 from rhodecode.model.meta import Session
45 from rhodecode.model.meta import Session
45 from rhodecode.model.repo import RepoModel
46 from rhodecode.model.repo import RepoModel
46 from rhodecode.model.comment import ChangesetCommentsModel
47 from rhodecode.model.comment import ChangesetCommentsModel
47 from rhodecode.model.changeset_status import ChangesetStatusModel
48 from rhodecode.model.changeset_status import ChangesetStatusModel
48
49
49 log = logging.getLogger(__name__)
50 log = logging.getLogger(__name__)
50
51
51
52
52 class PullrequestsController(BaseRepoController):
53 class PullrequestsController(BaseRepoController):
53
54
54 @LoginRequired()
55 @LoginRequired()
55 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
56 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
56 'repository.admin')
57 'repository.admin')
57 def __before__(self):
58 def __before__(self):
58 super(PullrequestsController, self).__before__()
59 super(PullrequestsController, self).__before__()
59
60
60 def _get_repo_refs(self, repo):
61 def _get_repo_refs(self, repo):
61 hist_l = []
62 hist_l = []
62
63
63 branches_group = ([('branch:%s:%s' % (k, v), k) for
64 branches_group = ([('branch:%s:%s' % (k, v), k) for
64 k, v in repo.branches.iteritems()], _("Branches"))
65 k, v in repo.branches.iteritems()], _("Branches"))
65 bookmarks_group = ([('book:%s:%s' % (k, v), k) for
66 bookmarks_group = ([('book:%s:%s' % (k, v), k) for
66 k, v in repo.bookmarks.iteritems()], _("Bookmarks"))
67 k, v in repo.bookmarks.iteritems()], _("Bookmarks"))
67 tags_group = ([('tag:%s:%s' % (k, v), k) for
68 tags_group = ([('tag:%s:%s' % (k, v), k) for
68 k, v in repo.tags.iteritems()], _("Tags"))
69 k, v in repo.tags.iteritems()], _("Tags"))
69
70
70 hist_l.append(bookmarks_group)
71 hist_l.append(bookmarks_group)
71 hist_l.append(branches_group)
72 hist_l.append(branches_group)
72 hist_l.append(tags_group)
73 hist_l.append(tags_group)
73
74
74 return hist_l
75 return hist_l
75
76
76 def show_all(self, repo_name):
77 def show_all(self, repo_name):
77 c.pull_requests = PullRequestModel().get_all(repo_name)
78 c.pull_requests = PullRequestModel().get_all(repo_name)
78 c.repo_name = repo_name
79 c.repo_name = repo_name
79 return render('/pullrequests/pullrequest_show_all.html')
80 return render('/pullrequests/pullrequest_show_all.html')
80
81
81 def index(self):
82 def index(self):
82 org_repo = c.rhodecode_db_repo
83 org_repo = c.rhodecode_db_repo
83
84
84 if org_repo.scm_instance.alias != 'hg':
85 if org_repo.scm_instance.alias != 'hg':
85 log.error('Review not available for GIT REPOS')
86 log.error('Review not available for GIT REPOS')
86 raise HTTPNotFound
87 raise HTTPNotFound
87
88
88 c.org_refs = self._get_repo_refs(c.rhodecode_repo)
89 c.org_refs = self._get_repo_refs(c.rhodecode_repo)
89 c.org_repos = []
90 c.org_repos = []
90 c.other_repos = []
91 c.other_repos = []
91 c.org_repos.append((org_repo.repo_name, '%s/%s' % (
92 c.org_repos.append((org_repo.repo_name, '%s/%s' % (
92 org_repo.user.username, c.repo_name))
93 org_repo.user.username, c.repo_name))
93 )
94 )
94
95
95 c.other_refs = c.org_refs
96 c.other_refs = c.org_refs
96 c.other_repos.extend(c.org_repos)
97 c.other_repos.extend(c.org_repos)
97 c.default_pull_request = org_repo.repo_name
98 c.default_pull_request = org_repo.repo_name
98 #gather forks and add to this list
99 #gather forks and add to this list
99 for fork in org_repo.forks:
100 for fork in org_repo.forks:
100 c.other_repos.append((fork.repo_name, '%s/%s' % (
101 c.other_repos.append((fork.repo_name, '%s/%s' % (
101 fork.user.username, fork.repo_name))
102 fork.user.username, fork.repo_name))
102 )
103 )
103 #add parents of this fork also
104 #add parents of this fork also
104 if org_repo.parent:
105 if org_repo.parent:
105 c.default_pull_request = org_repo.parent.repo_name
106 c.default_pull_request = org_repo.parent.repo_name
106 c.other_repos.append((org_repo.parent.repo_name, '%s/%s' % (
107 c.other_repos.append((org_repo.parent.repo_name, '%s/%s' % (
107 org_repo.parent.user.username,
108 org_repo.parent.user.username,
108 org_repo.parent.repo_name))
109 org_repo.parent.repo_name))
109 )
110 )
110
111
111 c.review_members = []
112 c.review_members = []
112 c.available_members = []
113 c.available_members = []
113 for u in User.query().filter(User.username != 'default').all():
114 for u in User.query().filter(User.username != 'default').all():
114 uname = u.username
115 uname = u.username
115 if org_repo.user == u:
116 if org_repo.user == u:
116 uname = _('%s (owner)' % u.username)
117 uname = _('%s (owner)' % u.username)
117 # auto add owner to pull-request recipients
118 # auto add owner to pull-request recipients
118 c.review_members.append([u.user_id, uname])
119 c.review_members.append([u.user_id, uname])
119 c.available_members.append([u.user_id, uname])
120 c.available_members.append([u.user_id, uname])
120 return render('/pullrequests/pullrequest.html')
121 return render('/pullrequests/pullrequest.html')
121
122
122 def create(self, repo_name):
123 def create(self, repo_name):
123 req_p = request.POST
124 req_p = request.POST
124 org_repo = req_p['org_repo']
125 org_repo = req_p['org_repo']
125 org_ref = req_p['org_ref']
126 org_ref = req_p['org_ref']
126 other_repo = req_p['other_repo']
127 other_repo = req_p['other_repo']
127 other_ref = req_p['other_ref']
128 other_ref = req_p['other_ref']
128 revisions = req_p.getall('revisions')
129 revisions = req_p.getall('revisions')
129 reviewers = req_p.getall('review_members')
130 reviewers = req_p.getall('review_members')
130 #TODO: wrap this into a FORM !!!
131 #TODO: wrap this into a FORM !!!
131
132
132 title = req_p['pullrequest_title']
133 title = req_p['pullrequest_title']
133 description = req_p['pullrequest_desc']
134 description = req_p['pullrequest_desc']
134
135
135 try:
136 try:
136 model = PullRequestModel()
137 model = PullRequestModel()
137 model.create(self.rhodecode_user.user_id, org_repo,
138 model.create(self.rhodecode_user.user_id, org_repo,
138 org_ref, other_repo, other_ref, revisions,
139 org_ref, other_repo, other_ref, revisions,
139 reviewers, title, description)
140 reviewers, title, description)
140 Session.commit()
141 Session.commit()
141 h.flash(_('Pull request send'), category='success')
142 h.flash(_('Pull request send'), category='success')
142 except Exception:
143 except Exception:
143 raise
144 raise
144 h.flash(_('Error occured during sending pull request'),
145 h.flash(_('Error occured during sending pull request'),
145 category='error')
146 category='error')
146 log.error(traceback.format_exc())
147 log.error(traceback.format_exc())
147
148
148 return redirect(url('changelog_home', repo_name=repo_name))
149 return redirect(url('changelog_home', repo_name=repo_name))
149
150
150 def _load_compare_data(self, pull_request):
151 def _load_compare_data(self, pull_request):
151 """
152 """
152 Load context data needed for generating compare diff
153 Load context data needed for generating compare diff
153
154
154 :param pull_request:
155 :param pull_request:
155 :type pull_request:
156 :type pull_request:
156 """
157 """
157
158
158 org_repo = pull_request.org_repo
159 org_repo = pull_request.org_repo
159 org_ref_type, org_ref_, org_ref = pull_request.org_ref.split(':')
160 org_ref_type, org_ref_, org_ref = pull_request.org_ref.split(':')
160 other_repo = pull_request.other_repo
161 other_repo = pull_request.other_repo
161 other_ref_type, other_ref, other_ref_ = pull_request.other_ref.split(':')
162 other_ref_type, other_ref, other_ref_ = pull_request.other_ref.split(':')
162
163
163 org_ref = (org_ref_type, org_ref)
164 org_ref = (org_ref_type, org_ref)
164 other_ref = (other_ref_type, other_ref)
165 other_ref = (other_ref_type, other_ref)
165
166
166 c.org_repo = org_repo
167 c.org_repo = org_repo
167 c.other_repo = other_repo
168 c.other_repo = other_repo
168
169
169 c.cs_ranges, discovery_data = PullRequestModel().get_compare_data(
170 c.cs_ranges, discovery_data = PullRequestModel().get_compare_data(
170 org_repo, org_ref, other_repo, other_ref
171 org_repo, org_ref, other_repo, other_ref
171 )
172 )
172
173
173 c.statuses = c.rhodecode_db_repo.statuses([x.raw_id for x in
174 c.statuses = c.rhodecode_db_repo.statuses([x.raw_id for x in
174 c.cs_ranges])
175 c.cs_ranges])
175 # defines that we need hidden inputs with changesets
176 # defines that we need hidden inputs with changesets
176 c.as_form = request.GET.get('as_form', False)
177 c.as_form = request.GET.get('as_form', False)
177
178
178 c.org_ref = org_ref[1]
179 c.org_ref = org_ref[1]
179 c.other_ref = other_ref[1]
180 c.other_ref = other_ref[1]
180 # diff needs to have swapped org with other to generate proper diff
181 # diff needs to have swapped org with other to generate proper diff
181 _diff = diffs.differ(other_repo, other_ref, org_repo, org_ref,
182 _diff = diffs.differ(other_repo, other_ref, org_repo, org_ref,
182 discovery_data)
183 discovery_data)
183 diff_processor = diffs.DiffProcessor(_diff, format='gitdiff')
184 diff_processor = diffs.DiffProcessor(_diff, format='gitdiff')
184 _parsed = diff_processor.prepare()
185 _parsed = diff_processor.prepare()
185
186
186 c.files = []
187 c.files = []
187 c.changes = {}
188 c.changes = {}
188
189
189 for f in _parsed:
190 for f in _parsed:
190 fid = h.FID('', f['filename'])
191 fid = h.FID('', f['filename'])
191 c.files.append([fid, f['operation'], f['filename'], f['stats']])
192 c.files.append([fid, f['operation'], f['filename'], f['stats']])
192 diff = diff_processor.as_html(enable_comments=False, diff_lines=[f])
193 diff = diff_processor.as_html(enable_comments=True,
194 diff_lines=[f])
193 c.changes[fid] = [f['operation'], f['filename'], diff]
195 c.changes[fid] = [f['operation'], f['filename'], diff]
194
196
195 def show(self, repo_name, pull_request_id):
197 def show(self, repo_name, pull_request_id):
196 repo_model = RepoModel()
198 repo_model = RepoModel()
197 c.users_array = repo_model.get_users_js()
199 c.users_array = repo_model.get_users_js()
198 c.users_groups_array = repo_model.get_users_groups_js()
200 c.users_groups_array = repo_model.get_users_groups_js()
199 c.pull_request = PullRequest.get(pull_request_id)
201 c.pull_request = PullRequest.get(pull_request_id)
200
202
201 # valid ID
203 # valid ID
202 if not c.pull_request:
204 if not c.pull_request:
203 raise HTTPNotFound
205 raise HTTPNotFound
204 cc_model = ChangesetCommentsModel()
206 cc_model = ChangesetCommentsModel()
205 cs_model = ChangesetStatusModel()
207 cs_model = ChangesetStatusModel()
206 _cs_statuses = cs_model.get_statuses(c.pull_request.org_repo,
208 _cs_statuses = cs_model.get_statuses(c.pull_request.org_repo,
207 pull_request=c.pull_request,
209 pull_request=c.pull_request,
208 with_revisions=True)
210 with_revisions=True)
209
211
210 cs_statuses = defaultdict(list)
212 cs_statuses = defaultdict(list)
211 for st in _cs_statuses:
213 for st in _cs_statuses:
212 cs_statuses[st.author.username] += [st]
214 cs_statuses[st.author.username] += [st]
213
215
214 c.pull_request_reviewers = []
216 c.pull_request_reviewers = []
215 for o in c.pull_request.reviewers:
217 for o in c.pull_request.reviewers:
216 st = cs_statuses.get(o.user.username, None)
218 st = cs_statuses.get(o.user.username, None)
217 if st:
219 if st:
218 sorter = lambda k: k.version
220 sorter = lambda k: k.version
219 st = [(x, list(y)[0])
221 st = [(x, list(y)[0])
220 for x, y in (groupby(sorted(st, key=sorter), sorter))]
222 for x, y in (groupby(sorted(st, key=sorter), sorter))]
221 c.pull_request_reviewers.append([o.user, st])
223 c.pull_request_reviewers.append([o.user, st])
222
224
223 # pull_requests repo_name we opened it against
225 # pull_requests repo_name we opened it against
224 # ie. other_repo must match
226 # ie. other_repo must match
225 if repo_name != c.pull_request.other_repo.repo_name:
227 if repo_name != c.pull_request.other_repo.repo_name:
226 raise HTTPNotFound
228 raise HTTPNotFound
227
229
228 # load compare data into template context
230 # load compare data into template context
229 self._load_compare_data(c.pull_request)
231 self._load_compare_data(c.pull_request)
230
232
231 # inline comments
233 # inline comments
232 c.inline_cnt = 0
234 c.inline_cnt = 0
233 c.inline_comments = cc_model.get_inline_comments(
235 c.inline_comments = cc_model.get_inline_comments(
234 c.rhodecode_db_repo.repo_id,
236 c.rhodecode_db_repo.repo_id,
235 pull_request=pull_request_id)
237 pull_request=pull_request_id)
236 # count inline comments
238 # count inline comments
237 for __, lines in c.inline_comments:
239 for __, lines in c.inline_comments:
238 for comments in lines.values():
240 for comments in lines.values():
239 c.inline_cnt += len(comments)
241 c.inline_cnt += len(comments)
240 # comments
242 # comments
241 c.comments = cc_model.get_comments(c.rhodecode_db_repo.repo_id,
243 c.comments = cc_model.get_comments(c.rhodecode_db_repo.repo_id,
242 pull_request=pull_request_id)
244 pull_request=pull_request_id)
243
245
244 # changeset(pull-request) status
246 # changeset(pull-request) status
245 c.current_changeset_status = cs_model.calculate_status(
247 c.current_changeset_status = cs_model.calculate_status(
246 c.pull_request_reviewers
248 c.pull_request_reviewers
247 )
249 )
248 c.changeset_statuses = ChangesetStatus.STATUSES
250 c.changeset_statuses = ChangesetStatus.STATUSES
249 c.target_repo = c.pull_request.org_repo.repo_name
251 c.target_repo = c.pull_request.org_repo.repo_name
250 return render('/pullrequests/pullrequest_show.html')
252 return render('/pullrequests/pullrequest_show.html')
251
253
252 @jsonify
254 @jsonify
253 def comment(self, repo_name, pull_request_id):
255 def comment(self, repo_name, pull_request_id):
254
256
255 status = request.POST.get('changeset_status')
257 status = request.POST.get('changeset_status')
256 change_status = request.POST.get('change_changeset_status')
258 change_status = request.POST.get('change_changeset_status')
257
259
258 comm = ChangesetCommentsModel().create(
260 comm = ChangesetCommentsModel().create(
259 text=request.POST.get('text'),
261 text=request.POST.get('text'),
260 repo_id=c.rhodecode_db_repo.repo_id,
262 repo_id=c.rhodecode_db_repo.repo_id,
261 user_id=c.rhodecode_user.user_id,
263 user_id=c.rhodecode_user.user_id,
262 pull_request=pull_request_id,
264 pull_request=pull_request_id,
263 f_path=request.POST.get('f_path'),
265 f_path=request.POST.get('f_path'),
264 line_no=request.POST.get('line'),
266 line_no=request.POST.get('line'),
265 status_change=(ChangesetStatus.get_status_lbl(status)
267 status_change=(ChangesetStatus.get_status_lbl(status)
266 if status and change_status else None)
268 if status and change_status else None)
267 )
269 )
268
270
269 # get status if set !
271 # get status if set !
270 if status and change_status:
272 if status and change_status:
271 ChangesetStatusModel().set_status(
273 ChangesetStatusModel().set_status(
272 c.rhodecode_db_repo.repo_id,
274 c.rhodecode_db_repo.repo_id,
273 status,
275 status,
274 c.rhodecode_user.user_id,
276 c.rhodecode_user.user_id,
275 comm,
277 comm,
276 pull_request=pull_request_id
278 pull_request=pull_request_id
277 )
279 )
278 action_logger(self.rhodecode_user,
280 action_logger(self.rhodecode_user,
279 'user_commented_pull_request:%s' % pull_request_id,
281 'user_commented_pull_request:%s' % pull_request_id,
280 c.rhodecode_db_repo, self.ip_addr, self.sa)
282 c.rhodecode_db_repo, self.ip_addr, self.sa)
281
283
282 Session.commit()
284 Session.commit()
283
285
284 if not request.environ.get('HTTP_X_PARTIAL_XHR'):
286 if not request.environ.get('HTTP_X_PARTIAL_XHR'):
285 return redirect(h.url('pullrequest_show', repo_name=repo_name,
287 return redirect(h.url('pullrequest_show', repo_name=repo_name,
286 pull_request_id=pull_request_id))
288 pull_request_id=pull_request_id))
287
289
288 data = {
290 data = {
289 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))),
291 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))),
290 }
292 }
291 if comm:
293 if comm:
292 c.co = comm
294 c.co = comm
293 data.update(comm.get_dict())
295 data.update(comm.get_dict())
294 data.update({'rendered_text':
296 data.update({'rendered_text':
295 render('changeset/changeset_comment_block.html')})
297 render('changeset/changeset_comment_block.html')})
296
298
297 return data
299 return data
300
301 @jsonify
302 def delete_comment(self, repo_name, comment_id):
303 co = ChangesetComment.get(comment_id)
304 owner = lambda: co.author.user_id == c.rhodecode_user.user_id
305 if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner:
306 ChangesetCommentsModel().delete(comment=co)
307 Session.commit()
308 return True
309 else:
310 raise HTTPForbidden() No newline at end of file
@@ -1,176 +1,176 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2
2
3 <%inherit file="/base/base.html"/>
3 <%inherit file="/base/base.html"/>
4
4
5 <%def name="title()">
5 <%def name="title()">
6 ${_('%s Changeset') % c.repo_name} - r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)} - ${c.rhodecode_name}
6 ${_('%s Changeset') % c.repo_name} - r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)} - ${c.rhodecode_name}
7 </%def>
7 </%def>
8
8
9 <%def name="breadcrumbs_links()">
9 <%def name="breadcrumbs_links()">
10 ${h.link_to(u'Home',h.url('/'))}
10 ${h.link_to(u'Home',h.url('/'))}
11 &raquo;
11 &raquo;
12 ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
12 ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
13 &raquo;
13 &raquo;
14 ${_('Changeset')} - <span class='hash'>r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)}</span>
14 ${_('Changeset')} - <span class='hash'>r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)}</span>
15 </%def>
15 </%def>
16
16
17 <%def name="page_nav()">
17 <%def name="page_nav()">
18 ${self.menu('changelog')}
18 ${self.menu('changelog')}
19 </%def>
19 </%def>
20
20
21 <%def name="main()">
21 <%def name="main()">
22 <div class="box">
22 <div class="box">
23 <!-- box / title -->
23 <!-- box / title -->
24 <div class="title">
24 <div class="title">
25 ${self.breadcrumbs()}
25 ${self.breadcrumbs()}
26 </div>
26 </div>
27 <div class="table">
27 <div class="table">
28 <div class="diffblock">
28 <div class="diffblock">
29 <div class="code-header">
29 <div class="code-header">
30 <div class="hash">
30 <div class="hash">
31 r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)}
31 r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)}
32 </div>
32 </div>
33 <div class="date">
33 <div class="date">
34 ${h.fmt_date(c.changeset.date)}
34 ${h.fmt_date(c.changeset.date)}
35 </div>
35 </div>
36 <div class="changeset-status-container">
36 <div class="changeset-status-container">
37 %if c.statuses:
37 %if c.statuses:
38 <div title="${_('Changeset status')}" class="changeset-status-lbl">[${h.changeset_status_lbl(c.statuses[0])}]</div>
38 <div title="${_('Changeset status')}" class="changeset-status-lbl">[${h.changeset_status_lbl(c.statuses[0])}]</div>
39 <div class="changeset-status-ico"><img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses[0])}" /></div>
39 <div class="changeset-status-ico"><img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses[0])}" /></div>
40 %endif
40 %endif
41 </div>
41 </div>
42 <div class="diff-actions">
42 <div class="diff-actions">
43 <a href="${h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='show')}" class="tooltip" title="${h.tooltip(_('raw diff'))}"><img class="icon" src="${h.url('/images/icons/page_white.png')}"/></a>
43 <a href="${h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='show')}" class="tooltip" title="${h.tooltip(_('raw diff'))}"><img class="icon" src="${h.url('/images/icons/page_white.png')}"/></a>
44 <a href="${h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='download')}" class="tooltip" title="${h.tooltip(_('download diff'))}"><img class="icon" src="${h.url('/images/icons/page_white_get.png')}"/></a>
44 <a href="${h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='download')}" class="tooltip" title="${h.tooltip(_('download diff'))}"><img class="icon" src="${h.url('/images/icons/page_white_get.png')}"/></a>
45 ${c.ignorews_url(request.GET)}
45 ${c.ignorews_url(request.GET)}
46 ${c.context_url(request.GET)}
46 ${c.context_url(request.GET)}
47 </div>
47 </div>
48 <div class="comments-number" style="float:right;padding-right:5px">${ungettext("%d comment", "%d comments", len(c.comments)) % len(c.comments)} ${ungettext("(%d inline)", "(%d inline)", c.inline_cnt) % c.inline_cnt}</div>
48 <div class="comments-number" style="float:right;padding-right:5px">${ungettext("%d comment", "%d comments", len(c.comments)) % len(c.comments)} ${ungettext("(%d inline)", "(%d inline)", c.inline_cnt) % c.inline_cnt}</div>
49 </div>
49 </div>
50 </div>
50 </div>
51 <div id="changeset_content">
51 <div id="changeset_content">
52 <div class="container">
52 <div class="container">
53 <div class="left">
53 <div class="left">
54 <div class="author">
54 <div class="author">
55 <div class="gravatar">
55 <div class="gravatar">
56 <img alt="gravatar" src="${h.gravatar_url(h.email(c.changeset.author),20)}"/>
56 <img alt="gravatar" src="${h.gravatar_url(h.email(c.changeset.author),20)}"/>
57 </div>
57 </div>
58 <span>${h.person(c.changeset.author)}</span><br/>
58 <span>${h.person(c.changeset.author)}</span><br/>
59 <span><a href="mailto:${h.email_or_none(c.changeset.author)}">${h.email_or_none(c.changeset.author)}</a></span><br/>
59 <span><a href="mailto:${h.email_or_none(c.changeset.author)}">${h.email_or_none(c.changeset.author)}</a></span><br/>
60 </div>
60 </div>
61 <div class="message">${h.urlify_commit(c.changeset.message, c.repo_name)}</div>
61 <div class="message">${h.urlify_commit(c.changeset.message, c.repo_name)}</div>
62 </div>
62 </div>
63 <div class="right">
63 <div class="right">
64 <div class="changes">
64 <div class="changes">
65 % if len(c.changeset.affected_files) <= c.affected_files_cut_off:
65 % if len(c.changeset.affected_files) <= c.affected_files_cut_off:
66 <span class="removed" title="${_('removed')}">${len(c.changeset.removed)}</span>
66 <span class="removed" title="${_('removed')}">${len(c.changeset.removed)}</span>
67 <span class="changed" title="${_('changed')}">${len(c.changeset.changed)}</span>
67 <span class="changed" title="${_('changed')}">${len(c.changeset.changed)}</span>
68 <span class="added" title="${_('added')}">${len(c.changeset.added)}</span>
68 <span class="added" title="${_('added')}">${len(c.changeset.added)}</span>
69 % else:
69 % else:
70 <span class="removed" title="${_('affected %s files') % len(c.changeset.affected_files)}">!</span>
70 <span class="removed" title="${_('affected %s files') % len(c.changeset.affected_files)}">!</span>
71 <span class="changed" title="${_('affected %s files') % len(c.changeset.affected_files)}">!</span>
71 <span class="changed" title="${_('affected %s files') % len(c.changeset.affected_files)}">!</span>
72 <span class="added" title="${_('affected %s files') % len(c.changeset.affected_files)}">!</span>
72 <span class="added" title="${_('affected %s files') % len(c.changeset.affected_files)}">!</span>
73 % endif
73 % endif
74 </div>
74 </div>
75
75
76 %if c.changeset.parents:
76 %if c.changeset.parents:
77 %for p_cs in reversed(c.changeset.parents):
77 %for p_cs in reversed(c.changeset.parents):
78 <div class="parent">${_('Parent')}
78 <div class="parent">${_('Parent')}
79 <span class="changeset_id">${p_cs.revision}:<span class="changeset_hash">${h.link_to(h.short_id(p_cs.raw_id),
79 <span class="changeset_id">${p_cs.revision}:<span class="changeset_hash">${h.link_to(h.short_id(p_cs.raw_id),
80 h.url('changeset_home',repo_name=c.repo_name,revision=p_cs.raw_id),title=p_cs.message)}</span></span>
80 h.url('changeset_home',repo_name=c.repo_name,revision=p_cs.raw_id),title=p_cs.message)}</span></span>
81 </div>
81 </div>
82 %endfor
82 %endfor
83 %else:
83 %else:
84 <div class="parent">${_('No parents')}</div>
84 <div class="parent">${_('No parents')}</div>
85 %endif
85 %endif
86 <span class="logtags">
86 <span class="logtags">
87 %if len(c.changeset.parents)>1:
87 %if len(c.changeset.parents)>1:
88 <span class="merge">${_('merge')}</span>
88 <span class="merge">${_('merge')}</span>
89 %endif
89 %endif
90 %if c.changeset.branch:
90 %if c.changeset.branch:
91 <span class="branchtag" title="${'%s %s' % (_('branch'),c.changeset.branch)}">
91 <span class="branchtag" title="${'%s %s' % (_('branch'),c.changeset.branch)}">
92 ${h.link_to(c.changeset.branch,h.url('files_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}
92 ${h.link_to(c.changeset.branch,h.url('files_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}
93 </span>
93 </span>
94 %endif
94 %endif
95 %for tag in c.changeset.tags:
95 %for tag in c.changeset.tags:
96 <span class="tagtag" title="${'%s %s' % (_('tag'),tag)}">
96 <span class="tagtag" title="${'%s %s' % (_('tag'),tag)}">
97 ${h.link_to(tag,h.url('files_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}</span>
97 ${h.link_to(tag,h.url('files_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}</span>
98 %endfor
98 %endfor
99 </span>
99 </span>
100 </div>
100 </div>
101 </div>
101 </div>
102 <span>
102 <span>
103 ${_('%s files affected with %s insertions and %s deletions:') % (len(c.changeset.affected_files),c.lines_added,c.lines_deleted)}
103 ${_('%s files affected with %s insertions and %s deletions:') % (len(c.changeset.affected_files),c.lines_added,c.lines_deleted)}
104 </span>
104 </span>
105 <div class="cs_files">
105 <div class="cs_files">
106 %for change,filenode,diff,cs1,cs2,stat in c.changes:
106 %for change,filenode,diff,cs1,cs2,stat in c.changes:
107 <div class="cs_${change}">
107 <div class="cs_${change}">
108 <div class="node">
108 <div class="node">
109 %if change != 'removed':
109 %if change != 'removed':
110 ${h.link_to(h.safe_unicode(filenode.path),c.anchor_url(filenode.changeset.raw_id,filenode.path,request.GET)+"_target")}
110 ${h.link_to(h.safe_unicode(filenode.path),c.anchor_url(filenode.changeset.raw_id,filenode.path,request.GET)+"_target")}
111 %else:
111 %else:
112 ${h.link_to(h.safe_unicode(filenode.path),h.url.current(anchor=h.FID('',filenode.path)))}
112 ${h.link_to(h.safe_unicode(filenode.path),h.url.current(anchor=h.FID('',filenode.path)))}
113 %endif
113 %endif
114 </div>
114 </div>
115 <div class="changes">${h.fancy_file_stats(stat)}</div>
115 <div class="changes">${h.fancy_file_stats(stat)}</div>
116 </div>
116 </div>
117 %endfor
117 %endfor
118 % if c.cut_off:
118 % if c.cut_off:
119 ${_('Changeset was too big and was cut off...')}
119 ${_('Changeset was too big and was cut off...')}
120 % endif
120 % endif
121 </div>
121 </div>
122 </div>
122 </div>
123
123
124 </div>
124 </div>
125 <script>
125 <script>
126 var _USERS_AC_DATA = ${c.users_array|n};
126 var _USERS_AC_DATA = ${c.users_array|n};
127 var _GROUPS_AC_DATA = ${c.users_groups_array|n};
127 var _GROUPS_AC_DATA = ${c.users_groups_array|n};
128 AJAX_COMMENT_URL = "${url('changeset_comment',repo_name=c.repo_name,revision=c.changeset.raw_id)}";
129 AJAX_COMMENT_DELETE_URL = "${url('changeset_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}";
128 </script>
130 </script>
129 ## diff block
131 ## diff block
130 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
132 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
131 ${diff_block.diff_block(c.changes)}
133 ${diff_block.diff_block(c.changes)}
132
134
133 ## template for inline comment form
135 ## template for inline comment form
134 <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
136 <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
135 ${comment.comment_inline_form(c.changeset)}
137 ${comment.comment_inline_form()}
136
138
137 ## render comments main comments form and it status
139 ## render comments main comments form and it status
138 ${comment.comments(h.url('changeset_comment', repo_name=c.repo_name, revision=c.changeset.raw_id),
140 ${comment.comments(h.url('changeset_comment', repo_name=c.repo_name, revision=c.changeset.raw_id),
139 h.changeset_status(c.rhodecode_db_repo, c.changeset.raw_id))}
141 h.changeset_status(c.rhodecode_db_repo, c.changeset.raw_id))}
140
142
143 ## FORM FOR MAKING JS ACTION AS CHANGESET COMMENTS
141 <script type="text/javascript">
144 <script type="text/javascript">
142 YUE.onDOMReady(function(){
145 YUE.onDOMReady(function(){
143 AJAX_COMMENT_URL = "${url('changeset_comment',repo_name=c.repo_name,revision=c.changeset.raw_id)}";
144 AJAX_COMMENT_DELETE_URL = "${url('changeset_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}"
145 YUE.on(YUQ('.show-inline-comments'),'change',function(e){
146 YUE.on(YUQ('.show-inline-comments'),'change',function(e){
146 var show = 'none';
147 var show = 'none';
147 var target = e.currentTarget;
148 var target = e.currentTarget;
148 if(target.checked){
149 if(target.checked){
149 var show = ''
150 var show = ''
150 }
151 }
151 var boxid = YUD.getAttribute(target,'id_for');
152 var boxid = YUD.getAttribute(target,'id_for');
152 var comments = YUQ('#{0} .inline-comments'.format(boxid));
153 var comments = YUQ('#{0} .inline-comments'.format(boxid));
153 for(c in comments){
154 for(c in comments){
154 YUD.setStyle(comments[c],'display',show);
155 YUD.setStyle(comments[c],'display',show);
155 }
156 }
156 var btns = YUQ('#{0} .inline-comments-button'.format(boxid));
157 var btns = YUQ('#{0} .inline-comments-button'.format(boxid));
157 for(c in btns){
158 for(c in btns){
158 YUD.setStyle(btns[c],'display',show);
159 YUD.setStyle(btns[c],'display',show);
159 }
160 }
160 })
161 })
161
162
162 YUE.on(YUQ('.line'),'click',function(e){
163 YUE.on(YUQ('.line'),'click',function(e){
163 var tr = e.currentTarget;
164 var tr = e.currentTarget;
164 injectInlineForm(tr);
165 injectInlineForm(tr);
165 });
166 });
166
167
167 // inject comments into they proper positions
168 // inject comments into they proper positions
168 var file_comments = YUQ('.inline-comment-placeholder');
169 var file_comments = YUQ('.inline-comment-placeholder');
169 renderInlineComments(file_comments);
170 renderInlineComments(file_comments);
170
171 })
171 })
172
172
173 </script>
173 </script>
174
174
175 </div>
175 </div>
176 </%def>
176 </%def>
@@ -1,154 +1,154 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 ## usage:
2 ## usage:
3 ## <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
3 ## <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
4 ## ${comment.comment_block(co)}
4 ## ${comment.comment_block(co)}
5 ##
5 ##
6 <%def name="comment_block(co)">
6 <%def name="comment_block(co)">
7 <div class="comment" id="comment-${co.comment_id}" line="${co.line_no}">
7 <div class="comment" id="comment-${co.comment_id}" line="${co.line_no}">
8 <div class="comment-wrapp">
8 <div class="comment-wrapp">
9 <div class="meta">
9 <div class="meta">
10 <div style="float:left"> <img src="${h.gravatar_url(co.author.email, 20)}" /> </div>
10 <div style="float:left"> <img src="${h.gravatar_url(co.author.email, 20)}" /> </div>
11 <div class="user">
11 <div class="user">
12 ${co.author.username}
12 ${co.author.username}
13 </div>
13 </div>
14 <div class="date">
14 <div class="date">
15 ${h.age(co.modified_at)}
15 ${h.age(co.modified_at)}
16 </div>
16 </div>
17 %if co.status_change:
17 %if co.status_change:
18 <div style="float:left" class="changeset-status-container">
18 <div style="float:left" class="changeset-status-container">
19 <div style="float:left;padding:0px 2px 0px 2px"><span style="font-size: 18px;">&rsaquo;</span></div>
19 <div style="float:left;padding:0px 2px 0px 2px"><span style="font-size: 18px;">&rsaquo;</span></div>
20 <div title="${_('Changeset status')}" class="changeset-status-lbl"> ${co.status_change.status_lbl}</div>
20 <div title="${_('Changeset status')}" class="changeset-status-lbl"> ${co.status_change.status_lbl}</div>
21 <div class="changeset-status-ico"><img src="${h.url(str('/images/icons/flag_status_%s.png' % co.status_change.status))}" /></div>
21 <div class="changeset-status-ico"><img src="${h.url(str('/images/icons/flag_status_%s.png' % co.status_change.status))}" /></div>
22 </div>
22 </div>
23 %endif
23 %endif
24 %if h.HasPermissionAny('hg.admin', 'repository.admin')() or co.author.user_id == c.rhodecode_user.user_id:
24 %if h.HasPermissionAny('hg.admin', 'repository.admin')() or co.author.user_id == c.rhodecode_user.user_id:
25 <div class="buttons">
25 <div class="buttons">
26 <span onClick="deleteComment(${co.comment_id})" class="delete-comment ui-btn">${_('Delete')}</span>
26 <span onClick="deleteComment(${co.comment_id})" class="delete-comment ui-btn">${_('Delete')}</span>
27 </div>
27 </div>
28 %endif
28 %endif
29 </div>
29 </div>
30 <div class="text">
30 <div class="text">
31 ${h.rst_w_mentions(co.text)|n}
31 ${h.rst_w_mentions(co.text)|n}
32 </div>
32 </div>
33 </div>
33 </div>
34 </div>
34 </div>
35 </%def>
35 </%def>
36
36
37
37
38 <%def name="comment_inline_form(changeset)">
38 <%def name="comment_inline_form()">
39 <div id='comment-inline-form-template' style="display:none">
39 <div id='comment-inline-form-template' style="display:none">
40 <div class="comment-inline-form ac">
40 <div class="comment-inline-form ac">
41 %if c.rhodecode_user.username != 'default':
41 %if c.rhodecode_user.username != 'default':
42 <div class="overlay"><div class="overlay-text">${_('Submitting...')}</div></div>
42 <div class="overlay"><div class="overlay-text">${_('Submitting...')}</div></div>
43 ${h.form(h.url('changeset_comment', repo_name=c.repo_name, revision=changeset.raw_id),class_='inline-form')}
43 ${h.form('#', class_='inline-form')}
44 <div class="clearfix">
44 <div class="clearfix">
45 <div class="comment-help">${_('Commenting on line {1}.')}
45 <div class="comment-help">${_('Commenting on line {1}.')}
46 ${(_('Comments parsed using %s syntax with %s support.') % (
46 ${(_('Comments parsed using %s syntax with %s support.') % (
47 ('<a href="%s">RST</a>' % h.url('rst_help')),
47 ('<a href="%s">RST</a>' % h.url('rst_help')),
48 ('<span style="color:#003367" class="tooltip" title="%s">@mention</span>' % _('Use @username inside this text to send notification to this RhodeCode user'))
48 ('<span style="color:#003367" class="tooltip" title="%s">@mention</span>' % _('Use @username inside this text to send notification to this RhodeCode user'))
49 )
49 )
50 )|n
50 )|n
51 }
51 }
52 </div>
52 </div>
53 <div class="mentions-container" id="mentions_container_{1}"></div>
53 <div class="mentions-container" id="mentions_container_{1}"></div>
54 <textarea id="text_{1}" name="text" class="yui-ac-input"></textarea>
54 <textarea id="text_{1}" name="text" class="yui-ac-input"></textarea>
55 </div>
55 </div>
56 <div class="comment-button">
56 <div class="comment-button">
57 <input type="hidden" name="f_path" value="{0}">
57 <input type="hidden" name="f_path" value="{0}">
58 <input type="hidden" name="line" value="{1}">
58 <input type="hidden" name="line" value="{1}">
59 ${h.submit('save', _('Comment'), class_='ui-btn save-inline-form')}
59 ${h.submit('save', _('Comment'), class_='ui-btn save-inline-form')}
60 ${h.reset('hide-inline-form', _('Hide'), class_='ui-btn hide-inline-form')}
60 ${h.reset('hide-inline-form', _('Hide'), class_='ui-btn hide-inline-form')}
61 </div>
61 </div>
62 ${h.end_form()}
62 ${h.end_form()}
63 %else:
63 %else:
64 ${h.form('')}
64 ${h.form('')}
65 <div class="clearfix">
65 <div class="clearfix">
66 <div class="comment-help">
66 <div class="comment-help">
67 ${_('You need to be logged in to comment.')} <a href="${h.url('login_home',came_from=h.url.current())}">${_('Login now')}</a>
67 ${_('You need to be logged in to comment.')} <a href="${h.url('login_home',came_from=h.url.current())}">${_('Login now')}</a>
68 </div>
68 </div>
69 </div>
69 </div>
70 <div class="comment-button">
70 <div class="comment-button">
71 ${h.reset('hide-inline-form', _('Hide'), class_='ui-btn hide-inline-form')}
71 ${h.reset('hide-inline-form', _('Hide'), class_='ui-btn hide-inline-form')}
72 </div>
72 </div>
73 ${h.end_form()}
73 ${h.end_form()}
74 %endif
74 %endif
75 </div>
75 </div>
76 </div>
76 </div>
77 </%def>
77 </%def>
78
78
79
79
80 ## generates inlines taken from c.comments var
80 ## generates inlines taken from c.comments var
81 <%def name="inlines()">
81 <%def name="inlines()">
82 <div class="comments-number">${ungettext("%d comment", "%d comments", len(c.comments)) % len(c.comments)} ${ungettext("(%d inline)", "(%d inline)", c.inline_cnt) % c.inline_cnt}</div>
82 <div class="comments-number">${ungettext("%d comment", "%d comments", len(c.comments)) % len(c.comments)} ${ungettext("(%d inline)", "(%d inline)", c.inline_cnt) % c.inline_cnt}</div>
83 %for path, lines in c.inline_comments:
83 %for path, lines in c.inline_comments:
84 % for line,comments in lines.iteritems():
84 % for line,comments in lines.iteritems():
85 <div style="display:none" class="inline-comment-placeholder" path="${path}" target_id="${h.safeid(h.safe_unicode(path))}">
85 <div style="display:none" class="inline-comment-placeholder" path="${path}" target_id="${h.safeid(h.safe_unicode(path))}">
86 %for co in comments:
86 %for co in comments:
87 ${comment_block(co)}
87 ${comment_block(co)}
88 %endfor
88 %endfor
89 </div>
89 </div>
90 %endfor
90 %endfor
91 %endfor
91 %endfor
92
92
93 </%def>
93 </%def>
94
94
95 ## MAIN COMMENT FORM
95 ## MAIN COMMENT FORM
96 <%def name="comments(post_url, cur_status)">
96 <%def name="comments(post_url, cur_status)">
97
97
98 <div class="comments">
98 <div class="comments">
99 <div id="inline-comments-container">
99 <div id="inline-comments-container">
100 ## generate inlines for this changeset
100 ## generate inlines for this changeset
101 ${inlines()}
101 ${inlines()}
102 </div>
102 </div>
103
103
104 %for co in c.comments:
104 %for co in c.comments:
105 <div id="comment-tr-${co.comment_id}">
105 <div id="comment-tr-${co.comment_id}">
106 ${comment_block(co)}
106 ${comment_block(co)}
107 </div>
107 </div>
108 %endfor
108 %endfor
109 %if c.rhodecode_user.username != 'default':
109 %if c.rhodecode_user.username != 'default':
110 <div class="comment-form ac">
110 <div class="comment-form ac">
111 ${h.form(post_url)}
111 ${h.form(post_url)}
112 <strong>${_('Leave a comment')}</strong>
112 <strong>${_('Leave a comment')}</strong>
113 <div class="clearfix">
113 <div class="clearfix">
114 <div class="comment-help">
114 <div class="comment-help">
115 ${(_('Comments parsed using %s syntax with %s support.') % (('<a href="%s">RST</a>' % h.url('rst_help')),
115 ${(_('Comments parsed using %s syntax with %s support.') % (('<a href="%s">RST</a>' % h.url('rst_help')),
116 '<span style="color:#003367" class="tooltip" title="%s">@mention</span>' %
116 '<span style="color:#003367" class="tooltip" title="%s">@mention</span>' %
117 _('Use @username inside this text to send notification to this RhodeCode user')))|n}
117 _('Use @username inside this text to send notification to this RhodeCode user')))|n}
118 | <label for="show_changeset_status_box" class="tooltip" title="${_('Check this to change current status of code-review for this changeset')}"> ${_('change status')}</label>
118 | <label for="show_changeset_status_box" class="tooltip" title="${_('Check this to change current status of code-review for this changeset')}"> ${_('change status')}</label>
119 <input style="vertical-align: bottom;margin-bottom:-2px" id="show_changeset_status_box" type="checkbox" name="change_changeset_status" />
119 <input style="vertical-align: bottom;margin-bottom:-2px" id="show_changeset_status_box" type="checkbox" name="change_changeset_status" />
120 </div>
120 </div>
121 <div id="status_block_container" class="status-block" style="display:none">
121 <div id="status_block_container" class="status-block" style="display:none">
122 %for status,lbl in c.changeset_statuses:
122 %for status,lbl in c.changeset_statuses:
123 <div class="">
123 <div class="">
124 <img src="${h.url('/images/icons/flag_status_%s.png' % status)}" /> <input ${'checked="checked"' if status == cur_status else ''}" type="radio" name="changeset_status" value="${status}"> <label>${lbl}</label>
124 <img src="${h.url('/images/icons/flag_status_%s.png' % status)}" /> <input ${'checked="checked"' if status == cur_status else ''}" type="radio" name="changeset_status" value="${status}"> <label>${lbl}</label>
125 </div>
125 </div>
126 %endfor
126 %endfor
127 </div>
127 </div>
128 <div class="mentions-container" id="mentions_container"></div>
128 <div class="mentions-container" id="mentions_container"></div>
129 ${h.textarea('text')}
129 ${h.textarea('text')}
130 </div>
130 </div>
131 <div class="comment-button">
131 <div class="comment-button">
132 ${h.submit('save', _('Comment'), class_='ui-button')}
132 ${h.submit('save', _('Comment'), class_='ui-button')}
133 </div>
133 </div>
134 ${h.end_form()}
134 ${h.end_form()}
135 </div>
135 </div>
136 %endif
136 %endif
137 </div>
137 </div>
138 <script>
138 <script>
139 YUE.onDOMReady(function () {
139 YUE.onDOMReady(function () {
140 MentionsAutoComplete('text', 'mentions_container', _USERS_AC_DATA, _GROUPS_AC_DATA);
140 MentionsAutoComplete('text', 'mentions_container', _USERS_AC_DATA, _GROUPS_AC_DATA);
141
141
142 // changeset status box listener
142 // changeset status box listener
143 YUE.on(YUD.get('show_changeset_status_box'),'change',function(e){
143 YUE.on(YUD.get('show_changeset_status_box'),'change',function(e){
144 if(e.currentTarget.checked){
144 if(e.currentTarget.checked){
145 YUD.setStyle('status_block_container','display','');
145 YUD.setStyle('status_block_container','display','');
146 }
146 }
147 else{
147 else{
148 YUD.setStyle('status_block_container','display','none');
148 YUD.setStyle('status_block_container','display','none');
149 }
149 }
150 })
150 })
151
151
152 });
152 });
153 </script>
153 </script>
154 </%def>
154 </%def>
@@ -1,104 +1,140 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} ${_('Pull request #%s') % c.pull_request.pull_request_id}
4 ${c.repo_name} ${_('Pull request #%s') % c.pull_request.pull_request_id}
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 ${_('Pull request #%s') % c.pull_request.pull_request_id}
12 ${_('Pull request #%s') % c.pull_request.pull_request_id}
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
22
23 <h3>${_('Title')}: ${c.pull_request.title}
23 <h3>${_('Title')}: ${c.pull_request.title}
24 <div class="changeset-status-container" style="float:none">
24 <div class="changeset-status-container" style="float:none">
25 %if c.current_changeset_status:
25 %if c.current_changeset_status:
26 <div title="${_('Pull request status')}" class="changeset-status-lbl">[${h.changeset_status_lbl(c.current_changeset_status)}]</div>
26 <div title="${_('Pull request status')}" class="changeset-status-lbl">[${h.changeset_status_lbl(c.current_changeset_status)}]</div>
27 <div class="changeset-status-ico" style="padding:4px"><img src="${h.url('/images/icons/flag_status_%s.png' % c.current_changeset_status)}" /></div>
27 <div class="changeset-status-ico" style="padding:4px"><img src="${h.url('/images/icons/flag_status_%s.png' % c.current_changeset_status)}" /></div>
28 %endif
28 %endif
29 </div>
29 </div>
30 </h3>
30 </h3>
31 <div style="white-space:pre-wrap;padding:3px 3px 5px 20px">${h.literal(c.pull_request.description)}</div>
31 <div style="white-space:pre-wrap;padding:3px 3px 5px 20px">${h.literal(c.pull_request.description)}</div>
32 <div style="padding:4px 4px 10px 20px">
32 <div style="padding:4px 4px 10px 20px">
33 <div>${_('Created on')}: ${h.fmt_date(c.pull_request.created_on)}</div>
33 <div>${_('Created on')}: ${h.fmt_date(c.pull_request.created_on)}</div>
34 </div>
34 </div>
35
35
36 ## REVIEWERS
36 ## REVIEWERS
37 <div>
37 <div>
38 <div class="table" style="float:right;width:46%;clear:none">
38 <div class="table" style="float:right;width:46%;clear:none">
39 <div id="body" class="diffblock">
39 <div id="body" class="diffblock">
40 <div style="white-space:pre-wrap;padding:5px">${_('Pull request reviewers')}</div>
40 <div style="white-space:pre-wrap;padding:5px">${_('Pull request reviewers')}</div>
41 </div>
41 </div>
42 <div style="border: 1px solid #CCC">
42 <div style="border: 1px solid #CCC">
43 <div class="group_members_wrap">
43 <div class="group_members_wrap">
44 <ul class="group_members">
44 <ul class="group_members">
45 %for user,status in c.pull_request_reviewers:
45 %for user,status in c.pull_request_reviewers:
46 <li>
46 <li>
47 <div class="group_member">
47 <div class="group_member">
48 <div style="float:left;padding:3px" class="tooltip" title="${h.tooltip(h.changeset_status_lbl(status[0][1].status if status else 'not_reviewed'))}">
48 <div style="float:left;padding:3px" class="tooltip" title="${h.tooltip(h.changeset_status_lbl(status[0][1].status if status else 'not_reviewed'))}">
49 <img src="${h.url(str('/images/icons/flag_status_%s.png' % (status[0][1].status if status else 'not_reviewed')))}"/>
49 <img src="${h.url(str('/images/icons/flag_status_%s.png' % (status[0][1].status if status else 'not_reviewed')))}"/>
50 </div>
50 </div>
51 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(user.email,20)}"/> </div>
51 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(user.email,20)}"/> </div>
52 <div style="float:left">${user.username}</div>
52 <div style="float:left">${user.username}</div>
53 </div>
53 </div>
54 </li>
54 </li>
55 %endfor
55 %endfor
56 </ul>
56 </ul>
57 </div>
57 </div>
58 </div>
58 </div>
59 </div>
59 </div>
60 ##DIFF
60 ##DIFF
61 <div class="table" style="float:left;width:46%;clear:none">
61 <div class="table" style="float:left;width:46%;clear:none">
62 <div id="body" class="diffblock">
62 <div id="body" class="diffblock">
63 <div style="white-space:pre-wrap;padding:5px">${_('Compare view')}</div>
63 <div style="white-space:pre-wrap;padding:5px">${_('Compare view')}</div>
64 </div>
64 </div>
65 <div id="changeset_compare_view_content">
65 <div id="changeset_compare_view_content">
66 ##CS
66 ##CS
67 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${_('Incoming changesets')}</div>
67 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${_('Incoming changesets')}</div>
68 <%include file="/compare/compare_cs.html" />
68 <%include file="/compare/compare_cs.html" />
69
69
70 ## FILES
70 ## FILES
71 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${_('Files affected')}</div>
71 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${_('Files affected')}</div>
72 <div class="cs_files">
72 <div class="cs_files">
73 %for fid, change, f, stat in c.files:
73 %for fid, change, f, stat in c.files:
74 <div class="cs_${change}">
74 <div class="cs_${change}">
75 <div class="node">${h.link_to(h.safe_unicode(f),h.url.current(anchor=fid))}</div>
75 <div class="node">${h.link_to(h.safe_unicode(f),h.url.current(anchor=fid))}</div>
76 <div class="changes">${h.fancy_file_stats(stat)}</div>
76 <div class="changes">${h.fancy_file_stats(stat)}</div>
77 </div>
77 </div>
78 %endfor
78 %endfor
79 </div>
79 </div>
80 </div>
80 </div>
81 </div>
81 </div>
82 </div>
82 </div>
83 <script>
83 <script>
84 var _USERS_AC_DATA = ${c.users_array|n};
84 var _USERS_AC_DATA = ${c.users_array|n};
85 var _GROUPS_AC_DATA = ${c.users_groups_array|n};
85 var _GROUPS_AC_DATA = ${c.users_groups_array|n};
86 AJAX_COMMENT_URL = "${url('pullrequest_comment',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id)}";
87 AJAX_COMMENT_DELETE_URL = "${url('pullrequest_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}";
86 </script>
88 </script>
87
89
88 ## diff block
90 ## diff block
89 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
91 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
90 %for fid, change, f, stat in c.files:
92 %for fid, change, f, stat in c.files:
91 ${diff_block.diff_block_simple([c.changes[fid]])}
93 ${diff_block.diff_block_simple([c.changes[fid]])}
92 %endfor
94 %endfor
93
95
94 ## template for inline comment form
96 ## template for inline comment form
95 <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
97 <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
96 ##${comment.comment_inline_form(c.changeset)}
98 ${comment.comment_inline_form()}
97
99
98 ## render comments main comments form and it status
100 ## render comments main comments form and it status
99 ${comment.comments(h.url('pullrequest_comment', repo_name=c.repo_name, pull_request_id=c.pull_request.pull_request_id),
101 ${comment.comments(h.url('pullrequest_comment', repo_name=c.repo_name, pull_request_id=c.pull_request.pull_request_id),
100 c.current_changeset_status)}
102 c.current_changeset_status)}
101
103
104
105 <script type="text/javascript">
106 YUE.onDOMReady(function(){
107
108 YUE.on(YUQ('.show-inline-comments'),'change',function(e){
109 var show = 'none';
110 var target = e.currentTarget;
111 if(target.checked){
112 var show = ''
113 }
114 var boxid = YUD.getAttribute(target,'id_for');
115 var comments = YUQ('#{0} .inline-comments'.format(boxid));
116 for(c in comments){
117 YUD.setStyle(comments[c],'display',show);
118 }
119 var btns = YUQ('#{0} .inline-comments-button'.format(boxid));
120 for(c in btns){
121 YUD.setStyle(btns[c],'display',show);
122 }
123 })
124
125 YUE.on(YUQ('.line'),'click',function(e){
126 var tr = e.currentTarget;
127 injectInlineForm(tr);
128 });
129
130 // inject comments into they proper positions
131 var file_comments = YUQ('.inline-comment-placeholder');
132 renderInlineComments(file_comments);
133 })
134
135 </script>
136
137
102 </div>
138 </div>
103
139
104 </%def>
140 </%def>
General Comments 0
You need to be logged in to leave comments. Login now