##// END OF EJS Templates
Added rest controllers for repos and users,...
Marcin Kuzminski -
r47:f6ac7918 default
parent child Browse files
Show More
@@ -0,0 +1,57 b''
1 import logging
2
3 from pylons import request, response, session, tmpl_context as c, url, app_globals as g
4 from pylons.controllers.util import abort, redirect
5 from pylons_app.lib import auth
6 from pylons_app.lib.base import BaseController, render
7
8 log = logging.getLogger(__name__)
9
10 class ReposController(BaseController):
11 """REST Controller styled on the Atom Publishing Protocol"""
12 # To properly map this controller, ensure your config/routing.py
13 # file has a resource setup:
14 # map.resource('repo', 'repos')
15 def __before__(self):
16 c.staticurl = g.statics
17 c.admin_user = session.get('admin_user')
18 c.admin_username = session.get('admin_username')
19
20 def index(self, format='html'):
21 """GET /repos: All items in the collection"""
22 # url('repos')
23 return render('/repos_manage.html')
24
25 def create(self):
26 """POST /repos: Create a new item"""
27 # url('repos')
28
29 def new(self, format='html'):
30 """GET /repos/new: Form to create a new item"""
31 # url('new_repo')
32
33 def update(self, id):
34 """PUT /repos/id: Update an existing item"""
35 # Forms posted to this method should contain a hidden field:
36 # <input type="hidden" name="_method" value="PUT" />
37 # Or using helpers:
38 # h.form(url('repo', id=ID),
39 # method='put')
40 # url('repo', id=ID)
41
42 def delete(self, id):
43 """DELETE /repos/id: Delete an existing item"""
44 # Forms posted to this method should contain a hidden field:
45 # <input type="hidden" name="_method" value="DELETE" />
46 # Or using helpers:
47 # h.form(url('repo', id=ID),
48 # method='delete')
49 # url('repo', id=ID)
50
51 def show(self, id, format='html'):
52 """GET /repos/id: Show a specific item"""
53 # url('repo', id=ID)
54
55 def edit(self, id, format='html'):
56 """GET /repos/id/edit: Form to edit an existing item"""
57 # url('edit_repo', id=ID)
@@ -0,0 +1,60 b''
1 import logging
2
3 from pylons import request, response, session, tmpl_context as c, url, app_globals as g
4 from pylons.controllers.util import abort, redirect
5
6 from pylons_app.lib.base import BaseController, render
7 from pylons_app.lib import auth
8 log = logging.getLogger(__name__)
9
10 class UsersController(BaseController):
11 """REST Controller styled on the Atom Publishing Protocol"""
12 # To properly map this controller, ensure your config/routing.py
13 # file has a resource setup:
14 # map.resource('user', 'users')
15 def __before__(self):
16 c.staticurl = g.statics
17 c.admin_user = session.get('admin_user')
18 c.admin_username = session.get('admin_username')
19
20 def index(self, format='html'):
21 """GET /users: All items in the collection"""
22 # url('users')
23 conn, cur = auth.get_sqlite_conn_cur()
24 cur.execute('SELECT * FROM users')
25 c.users_list = cur.fetchall()
26 return render('/users_manage.html')
27
28 def create(self):
29 """POST /users: Create a new item"""
30 # url('users')
31
32 def new(self, format='html'):
33 """GET /users/new: Form to create a new item"""
34 # url('new_user')
35
36 def update(self, id):
37 """PUT /users/id: Update an existing item"""
38 # Forms posted to this method should contain a hidden field:
39 # <input type="hidden" name="_method" value="PUT" />
40 # Or using helpers:
41 # h.form(url('user', id=ID),
42 # method='put')
43 # url('user', id=ID)
44
45 def delete(self, id):
46 """DELETE /users/id: Delete an existing item"""
47 # Forms posted to this method should contain a hidden field:
48 # <input type="hidden" name="_method" value="DELETE" />
49 # Or using helpers:
50 # h.form(url('user', id=ID),
51 # method='delete')
52 # url('user', id=ID)
53
54 def show(self, id, format='html'):
55 """GET /users/id: Show a specific item"""
56 # url('user', id=ID)
57
58 def edit(self, id, format='html'):
59 """GET /users/id/edit: Form to edit an existing item"""
60 # url('edit_user', id=ID)
@@ -0,0 +1,43 b''
1 from pylons_app.tests import *
2
3 class TestReposController(TestController):
4
5 def test_index(self):
6 response = self.app.get(url('repos'))
7 # Test response...
8
9 def test_index_as_xml(self):
10 response = self.app.get(url('formatted_repos', format='xml'))
11
12 def test_create(self):
13 response = self.app.post(url('repos'))
14
15 def test_new(self):
16 response = self.app.get(url('new_repo'))
17
18 def test_new_as_xml(self):
19 response = self.app.get(url('formatted_new_repo', format='xml'))
20
21 def test_update(self):
22 response = self.app.put(url('repo', id=1))
23
24 def test_update_browser_fakeout(self):
25 response = self.app.post(url('repo', id=1), params=dict(_method='put'))
26
27 def test_delete(self):
28 response = self.app.delete(url('repo', id=1))
29
30 def test_delete_browser_fakeout(self):
31 response = self.app.post(url('repo', id=1), params=dict(_method='delete'))
32
33 def test_show(self):
34 response = self.app.get(url('repo', id=1))
35
36 def test_show_as_xml(self):
37 response = self.app.get(url('formatted_repo', id=1, format='xml'))
38
39 def test_edit(self):
40 response = self.app.get(url('edit_repo', id=1))
41
42 def test_edit_as_xml(self):
43 response = self.app.get(url('formatted_edit_repo', id=1, format='xml'))
@@ -0,0 +1,43 b''
1 from pylons_app.tests import *
2
3 class TestUsersController(TestController):
4
5 def test_index(self):
6 response = self.app.get(url('users'))
7 # Test response...
8
9 def test_index_as_xml(self):
10 response = self.app.get(url('formatted_users', format='xml'))
11
12 def test_create(self):
13 response = self.app.post(url('users'))
14
15 def test_new(self):
16 response = self.app.get(url('new_user'))
17
18 def test_new_as_xml(self):
19 response = self.app.get(url('formatted_new_user', format='xml'))
20
21 def test_update(self):
22 response = self.app.put(url('user', id=1))
23
24 def test_update_browser_fakeout(self):
25 response = self.app.post(url('user', id=1), params=dict(_method='put'))
26
27 def test_delete(self):
28 response = self.app.delete(url('user', id=1))
29
30 def test_delete_browser_fakeout(self):
31 response = self.app.post(url('user', id=1), params=dict(_method='delete'))
32
33 def test_show(self):
34 response = self.app.get(url('user', id=1))
35
36 def test_show_as_xml(self):
37 response = self.app.get(url('formatted_user', id=1, format='xml'))
38
39 def test_edit(self):
40 response = self.app.get(url('edit_user', id=1))
41
42 def test_edit_as_xml(self):
43 response = self.app.get(url('formatted_edit_user', id=1, format='xml'))
@@ -1,31 +1,32 b''
1 1 """Routes configuration
2 2
3 3 The more specific and detailed routes should be defined first so they
4 4 may take precedent over the more generic routes. For more information
5 5 refer to the routes manual at http://routes.groovie.org/docs/
6 6 """
7 7 from routes import Mapper
8 8
9 9 def make_map(config):
10 10 """Create, configure and return the routes Mapper"""
11 11 map = Mapper(directory=config['pylons.paths']['controllers'],
12 12 always_scan=config['debug'])
13 13 map.minimization = False
14 14 map.explicit = False
15 15
16 16 # The ErrorController route (handles 404/500 error pages); it should
17 17 # likely stay at the top, ensuring it can always be resolved
18 18 map.connect('/error/{action}', controller='error')
19 19 map.connect('/error/{action}/{id}', controller='error')
20 20
21 21 # CUSTOM ROUTES HERE
22 22 with map.submapper(path_prefix='/_admin', controller='admin') as m:
23 23 m.connect('admin_home', '/', action='index')#main page
24 24 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}', action='add_repo')
25 m.connect('admin_users_manage', '/repos_manage', action='users_manage')
26 m.connect('admin_repos_manage', '/users_manage', action='repos_manage')
25
26 map.resource('repo', 'repos', path_prefix='/_admin')
27 map.resource('user', 'users', path_prefix='/_admin')
27 28
28 29 map.connect('hg', '/{path_info:.*}', controller='hg',
29 30 action="view", path_info='/')
30 31
31 32 return map
@@ -1,127 +1,115 b''
1 1 import logging
2 2
3 3 from pylons import request, response, session, tmpl_context as c, url, app_globals as g
4 4 from pylons.controllers.util import abort, redirect
5 5
6 6 from pylons_app.lib.base import BaseController, render
7 7 import os
8 8 from mercurial import ui, hg
9 9 from mercurial.error import RepoError
10 10 from ConfigParser import ConfigParser
11 11 from pylons_app.lib import auth
12 12 from pylons_app.model.forms import LoginForm
13 13 import formencode
14 14 import formencode.htmlfill as htmlfill
15 15 log = logging.getLogger(__name__)
16 16
17 17 class AdminController(BaseController):
18 18
19 19
20 20 def __before__(self):
21 21 c.staticurl = g.statics
22 22 c.admin_user = session.get('admin_user')
23 23 c.admin_username = session.get('admin_username')
24 24
25 25 def index(self):
26 26 # Return a rendered template
27 27 if request.POST:
28 28 #import Login Form validator class
29 29 login_form = LoginForm()
30 30
31 31 try:
32 32 c.form_result = login_form.to_python(dict(request.params))
33 33 if auth.admin_auth(c.form_result['username'], c.form_result['password']):
34 34 session['admin_user'] = True
35 35 session['admin_username'] = c.form_result['username']
36 36 session.save()
37 37 return redirect(url('admin_home'))
38 38 else:
39 39 raise formencode.Invalid('Login Error', None, None,
40 40 error_dict={'username':'invalid login',
41 41 'password':'invalid password'})
42 42
43 43 except formencode.Invalid, error:
44 44 c.form_result = error.value
45 45 c.form_errors = error.error_dict or {}
46 46 html = render('/admin.html')
47 47
48 48 return htmlfill.render(
49 49 html,
50 50 defaults=c.form_result,
51 51 encoding="UTF-8"
52 52 )
53 53 return render('/admin.html')
54 54
55 def repos_manage(self):
56 return render('/repos_manage.html')
57
58 def users_manage(self):
59 conn, cur = auth.get_sqlite_conn_cur()
60 cur.execute('SELECT * FROM users')
61 c.users_list = cur.fetchall()
62 return render('/users_manage.html')
63
64 def manage_hgrc(self):
65 pass
66
67 55 def hgrc(self, dirname):
68 56 filename = os.path.join(dirname, '.hg', 'hgrc')
69 57 return filename
70 58
71 59 def add_repo(self, new_repo):
72 60
73 61
74 62 #extra check it can be add since it's the command
75 63 if new_repo == '_admin':
76 64 c.msg = 'DENIED'
77 65 c.new_repo = ''
78 66 return render('add.html')
79 67
80 68 new_repo = new_repo.replace(" ", "_")
81 69 new_repo = new_repo.replace("-", "_")
82 70
83 71 try:
84 72 self._create_repo(new_repo)
85 73 c.new_repo = new_repo
86 74 c.msg = 'added repo'
87 75 except Exception as e:
88 76 c.new_repo = 'Exception when adding: %s' % new_repo
89 77 c.msg = str(e)
90 78
91 79 return render('add.html')
92 80
93 81 def _check_repo(self, repo_name):
94 82 p = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
95 83 config_path = os.path.join(p, 'hgwebdir.config')
96 84
97 85 cp = ConfigParser()
98 86
99 87 cp.read(config_path)
100 88 repos_path = cp.get('paths', '/').replace("**", '')
101 89
102 90 if not repos_path:
103 91 raise Exception('Could not read config !')
104 92
105 93 self.repo_path = os.path.join(repos_path, repo_name)
106 94
107 95 try:
108 96 r = hg.repository(ui.ui(), self.repo_path)
109 97 hg.verify(r)
110 98 #here we hnow that repo exists it was verified
111 99 log.info('%s repo is already created', repo_name)
112 100 raise Exception('Repo exists')
113 101 except RepoError:
114 102 log.info('%s repo is free for creation', repo_name)
115 103 #it means that there is no valid repo there...
116 104 return True
117 105
118 106
119 107 def _create_repo(self, repo_name):
120 108 if repo_name in [None, '', 'add']:
121 109 raise Exception('undefined repo_name of repo')
122 110
123 111 if self._check_repo(repo_name):
124 112 log.info('creating repo %s in %s', repo_name, self.repo_path)
125 113 cmd = """mkdir %s && hg init %s""" \
126 114 % (self.repo_path, self.repo_path)
127 115 os.popen(cmd)
@@ -1,500 +1,502 b''
1 1 /*** Initial Settings ***/
2 2 * {
3 3 margin: 0;
4 4 padding: 0;
5 5 font-weight: normal;
6 6 font-style: normal;
7 7 }
8 8
9 9 html {
10 10 font-size: 100%;
11 11 font-family: sans-serif;
12 12 }
13 13
14 14 body {
15 15 font-size: 77%;
16 16 margin: 15px 50px;
17 17 background: #4B4B4C;
18 18 }
19 19
20 20 a {
21 21 color:#0000cc;
22 22 text-decoration: none;
23 23 }
24 24 /*** end of Initial Settings ***/
25 25
26 26
27 27 /** common settings **/
28 28 div#container {
29 29 background: #FFFFFF;
30 30 position: relative;
31 31 color: #666;
32 32 }
33 33
34 34 div.page-header {
35 35 padding: 50px 20px 0;
36 36 background: #006699 top left repeat-x;
37 37 position: relative;
38 38 }
39 39 div.page-header h1 {
40 40 margin: 10px 0 30px;
41 41 font-size: 1.8em;
42 42 font-weight: bold;
43 43 font-family: osaka,'MS P Gothic', Georgia, serif;
44 44 letter-spacing: 1px;
45 45 color: #DDD;
46 46 }
47 47 div.page-header h1 a {
48 48 font-weight: bold;
49 49 color: #FFF;
50 50 }
51 51 div.page-header a {
52 52 text-decoration: none;
53 53 }
54 54 div.rss_logo {
55 55 float: right; white-space: nowrap;
56 56 }
57 57 div.rss_logo a {
58 58 padding:3px 6px; line-height:10px;
59 59 border:1px solid; border-color:#fcc7a5 #7d3302 #3e1a01 #ff954e;
60 60 color:#ffffff; background-color:#ff6600;
61 61 font-weight:bold; font-family:sans-serif; font-size:10px;
62 62 text-align:center; text-decoration:none;
63 63 }
64 64 div.rss_logo a:hover {
65 65 background-color:#ee5500;
66 66 }
67 67
68 68 td.indexlinks {
69 69 white-space: nowrap;
70 70 }
71 71 td.indexlinks a {
72 72 padding: 2px 5px; line-height: 10px;
73 73 border: 1px solid;
74 74 color: #ffffff; background-color: #7777bb;
75 75 border-color: #aaaadd #333366 #333366 #aaaadd;
76 76 font-weight: bold; text-align: center; text-decoration: none;
77 77 font-size: 10px;
78 78 }
79 79 td.indexlinks a:hover {
80 80 background-color: #6666aa;
81 81 }
82 82
83 83 div.page-header form {
84 84 position: absolute;
85 85 margin-bottom: 2px;
86 86 bottom: 0;
87 87 right: 20px;
88 88 }
89 89 div.page-header form label {
90 90 color: #DDD;
91 91 }
92 92 div.page-header form input {
93 93 padding: 2px;
94 94 border: solid 1px #DDD;
95 95 }
96 96 div.page-header form dl {
97 97 overflow: hidden;
98 98 }
99 99 div.page-header form dl dt {
100 100 font-size: 1.2em;
101 101 }
102 102 div.page-header form dl dt,
103 103 div.page-header form dl dd {
104 104 margin: 0 0 0 5px;
105 105 float: left;
106 106 height: 24px;
107 107 line-height: 20px;
108 108 }
109 109
110 110 ul.page-nav {
111 111 margin: 10px 0 0 0;
112 112 list-style-type: none;
113 113 overflow: hidden;
114 114 width: 800px;
115 115 }
116 116 ul.page-nav li {
117 117 margin: 0 2px 0 0;
118 118 float: left;
119 119 width: 80px;
120 120 height: 24px;
121 121 font-size: 1.1em;
122 122 line-height: 24px;
123 123 text-align: center;
124 124 }
125 125 ul.page-nav li.current {
126 126 background: #FFF;
127 127 }
128 128 ul.page-nav li a {
129 129 height: 24px;
130 130 color: #666;
131 131 background: #DDD;
132 132 display: block;
133 133 text-decoration: none;
134 134 }
135 135 ul.page-nav li a:hover {
136 136 color:#333;
137 137 background: #FFF;
138 138 }
139 139
140 140 ul.submenu {
141 141 margin: 10px 0 -10px 20px;
142 142 list-style-type: none;
143 143 }
144 144 ul.submenu li {
145 145 margin: 0 10px 0 0;
146 146 font-size: 1.2em;
147 147 display: inline;
148 148 }
149
149 ul.submenu li.current_submenu {
150 border-bottom: 2px solid #006699;
151 }
150 152 h2 {
151 153 margin: 20px 0 10px;
152 154 height: 30px;
153 155 line-height: 30px;
154 156 text-indent: 20px;
155 157 background: #FFF;
156 158 font-size: 1.2em;
157 159 border-top: dotted 1px #D5E1E6;
158 160 font-weight: bold;
159 161 }
160 162 h2.no-link {
161 163 color:#006699;
162 164 }
163 165 h2.no-border {
164 166 color: #FFF;
165 167 background: #006699;
166 168 border: 0;
167 169 }
168 170 h2 a {
169 171 font-weight:bold;
170 172 color:#006699;
171 173 }
172 174
173 175 div.page-path {
174 176 text-align: right;
175 177 padding: 20px 30px 10px 0;
176 178 border:solid #d9d8d1;
177 179 border-width:0px 0px 1px;
178 180 font-size: 1.2em;
179 181 }
180 182
181 183 div.page-footer {
182 184 margin: 50px 0 0;
183 185 position: relative;
184 186 }
185 187 div.page-footer p {
186 188 position: relative;
187 189 left: 20px;
188 190 bottom: 5px;
189 191 font-size: 1.2em;
190 192 }
191 193
192 194 ul.rss-logo {
193 195 position: absolute;
194 196 top: -10px;
195 197 right: 20px;
196 198 height: 20px;
197 199 list-style-type: none;
198 200 }
199 201 ul.rss-logo li {
200 202 display: inline;
201 203 }
202 204 ul.rss-logo li a {
203 205 padding: 3px 6px;
204 206 line-height: 10px;
205 207 border:1px solid;
206 208 border-color:#fcc7a5 #7d3302 #3e1a01 #ff954e;
207 209 color:#ffffff;
208 210 background-color:#ff6600;
209 211 font-weight:bold;
210 212 font-family:sans-serif;
211 213 font-size:10px;
212 214 text-align:center;
213 215 text-decoration:none;
214 216 }
215 217 div.rss-logo li a:hover {
216 218 background-color:#ee5500;
217 219 }
218 220
219 221 p.normal {
220 222 margin: 20px 0 20px 30px;
221 223 font-size: 1.2em;
222 224 }
223 225
224 226 table {
225 227 margin: 10px 0 0 20px;
226 228 width: auto;
227 229 border-collapse: collapse;
228 230 }
229 231 table tr td {
230 232 font-size: 1.1em;
231 233 }
232 234 table tr td.nowrap {
233 235 white-space: nowrap;
234 236 }
235 237 /*
236 238 table tr.parity0:hover,
237 239 table tr.parity1:hover {
238 240 background: #D5E1E6;
239 241 }
240 242 */
241 243 table tr.parity0 {
242 244 background: #F1F6F7;
243 245 }
244 246 table tr.parity1 {
245 247 background: #FFFFFF;
246 248 }
247 249 table tr td {
248 250 padding: 5px 5px;
249 251 }
250 252 table.annotated tr td {
251 253 padding: 0px 5px;
252 254 }
253 255
254 256 span.logtags span {
255 257 padding: 2px 6px;
256 258 font-weight: normal;
257 259 font-size: 11px;
258 260 border: 1px solid;
259 261 background-color: #ffaaff;
260 262 border-color: #ffccff #ff00ee #ff00ee #ffccff;
261 263 }
262 264 span.logtags span.tagtag {
263 265 background-color: #ffffaa;
264 266 border-color: #ffffcc #ffee00 #ffee00 #ffffcc;
265 267 }
266 268 span.logtags span.branchtag {
267 269 background-color: #aaffaa;
268 270 border-color: #ccffcc #00cc33 #00cc33 #ccffcc;
269 271 }
270 272 span.logtags span.inbranchtag {
271 273 background-color: #d5dde6;
272 274 border-color: #e3ecf4 #9398f4 #9398f4 #e3ecf4;
273 275 }
274 276
275 277 div.diff pre {
276 278 margin: 10px 0 0 0;
277 279 }
278 280 div.diff pre span {
279 281 font-family: monospace;
280 282 white-space: pre;
281 283 font-size: 1.2em;
282 284 padding: 3px 0;
283 285 }
284 286 td.source {
285 287 white-space: pre;
286 288 font-family: monospace;
287 289 margin: 10px 30px 0;
288 290 font-size: 1.2em;
289 291 font-family: monospace;
290 292 }
291 293 div.source div.parity0,
292 294 div.source div.parity1 {
293 295 padding: 1px;
294 296 font-size: 1.2em;
295 297 }
296 298 div.source div.parity0 {
297 299 background: #F1F6F7;
298 300 }
299 301 div.source div.parity1 {
300 302 background: #FFFFFF;
301 303 }
302 304 div.parity0:hover,
303 305 div.parity1:hover {
304 306 background: #D5E1E6;
305 307 }
306 308 .linenr {
307 309 color: #999;
308 310 text-align: right;
309 311 }
310 312 .lineno {
311 313 text-align: right;
312 314 }
313 315 .lineno a {
314 316 color: #999;
315 317 }
316 318 td.linenr {
317 319 width: 60px;
318 320 }
319 321
320 322 div#powered-by {
321 323 position: absolute;
322 324 width: 75px;
323 325 top: 15px;
324 326 right: 20px;
325 327 font-size: 1.2em;
326 328 }
327 329 div#powered-by a {
328 330 color: #EEE;
329 331 text-decoration: none;
330 332 }
331 333 div#powered-by a:hover {
332 334 text-decoration: underline;
333 335 }
334 336 /*
335 337 div#monoblue-corner-top-left {
336 338 position: absolute;
337 339 top: 0;
338 340 left: 0;
339 341 width: 10px;
340 342 height: 10px;
341 343 background: url(./monoblue-corner.png) top left no-repeat !important;
342 344 background: none;
343 345 }
344 346 div#monoblue-corner-top-right {
345 347 position: absolute;
346 348 top: 0;
347 349 right: 0;
348 350 width: 10px;
349 351 height: 10px;
350 352 background: url(./monoblue-corner.png) top right no-repeat !important;
351 353 background: none;
352 354 }
353 355 div#monoblue-corner-bottom-left {
354 356 position: absolute;
355 357 bottom: 0;
356 358 left: 0;
357 359 width: 10px;
358 360 height: 10px;
359 361 background: url(./monoblue-corner.png) bottom left no-repeat !important;
360 362 background: none;
361 363 }
362 364 div#monoblue-corner-bottom-right {
363 365 position: absolute;
364 366 bottom: 0;
365 367 right: 0;
366 368 width: 10px;
367 369 height: 10px;
368 370 background: url(./monoblue-corner.png) bottom right no-repeat !important;
369 371 background: none;
370 372 }
371 373 */
372 374 /** end of common settings **/
373 375
374 376 /** summary **/
375 377 dl.overview {
376 378 margin: 0 0 0 30px;
377 379 font-size: 1.1em;
378 380 overflow: hidden;
379 381 }
380 382 dl.overview dt,
381 383 dl.overview dd {
382 384 margin: 5px 0;
383 385 float: left;
384 386 }
385 387 dl.overview dt {
386 388 clear: left;
387 389 font-weight: bold;
388 390 width: 150px;
389 391 }
390 392 /** end of summary **/
391 393
392 394 /** chagelog **/
393 395 h3.changelog {
394 396 margin: 20px 0 5px 30px;
395 397 padding: 0 0 2px;
396 398 font-size: 1.4em;
397 399 border-bottom: dotted 1px #D5E1E6;
398 400 }
399 401 ul.changelog-entry {
400 402 margin: 0 0 10px 30px;
401 403 list-style-type: none;
402 404 position: relative;
403 405 }
404 406 ul.changelog-entry li span.revdate {
405 407 font-size: 1.1em;
406 408 }
407 409 ul.changelog-entry li.age {
408 410 position: absolute;
409 411 top: -25px;
410 412 right: 10px;
411 413 font-size: 1.4em;
412 414 color: #CCC;
413 415 font-weight: bold;
414 416 font-style: italic;
415 417 }
416 418 ul.changelog-entry li span.name {
417 419 font-size: 1.2em;
418 420 font-weight: bold;
419 421 }
420 422 ul.changelog-entry li.description {
421 423 margin: 10px 0 0;
422 424 font-size: 1.1em;
423 425 }
424 426 /** end of changelog **/
425 427
426 428 /** file **/
427 429 p.files {
428 430 margin: 0 0 0 20px;
429 431 font-size: 2.0em;
430 432 font-weight: bold;
431 433 }
432 434 /** end of file **/
433 435
434 436 /** changeset **/
435 437 h3.changeset {
436 438 margin: 20px 0 5px 20px;
437 439 padding: 0 0 2px;
438 440 font-size: 1.6em;
439 441 border-bottom: dotted 1px #D5E1E6;
440 442 }
441 443 p.changeset-age {
442 444 position: relative;
443 445 }
444 446 p.changeset-age span {
445 447 position: absolute;
446 448 top: -25px;
447 449 right: 10px;
448 450 font-size: 1.4em;
449 451 color: #CCC;
450 452 font-weight: bold;
451 453 font-style: italic;
452 454 }
453 455 p.description {
454 456 margin: 10px 30px 0 30px;
455 457 padding: 10px;
456 458 border: solid 1px #CCC;
457 459 font-size: 1.2em;
458 460 }
459 461 /** end of changeset **/
460 462
461 463 /** canvas **/
462 464 div#wrapper {
463 465 position: relative;
464 466 font-size: 1.2em;
465 467 }
466 468
467 469 canvas {
468 470 position: absolute;
469 471 z-index: 5;
470 472 top: -0.7em;
471 473 }
472 474
473 475 ul#nodebgs li.parity0 {
474 476 background: #F1F6F7;
475 477 }
476 478
477 479 ul#nodebgs li.parity1 {
478 480 background: #FFFFFF;
479 481 }
480 482
481 483 ul#graphnodes {
482 484 position: absolute;
483 485 z-index: 10;
484 486 top: 7px;
485 487 list-style: none inside none;
486 488 }
487 489
488 490 ul#nodebgs {
489 491 list-style: none inside none;
490 492 }
491 493
492 494 ul#graphnodes li, ul#nodebgs li {
493 495 height: 39px;
494 496 }
495 497
496 498 ul#graphnodes li .info {
497 499 display: block;
498 500 position: relative;
499 501 }
500 502 /** end of canvas **/
@@ -1,64 +1,64 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="base/base.html"/>
3 3 <%def name="get_form_error(element)">
4 4 %if type(c.form_errors) == dict:
5 5 %if c.form_errors.get(element,False):
6 6 <span class="error-message">
7 7 ${c.form_errors.get(element,'')}
8 8 </span>
9 9 %endif
10 10 %endif
11 11 </%def>
12 12 <%def name="title()">
13 13 ${_('Repository managment')}
14 14 </%def>
15 15 <%def name="breadcrumbs()">
16 16 ${h.link_to(u'Home',h.url('/'))}
17 17 /
18 18 ${h.link_to(u'Admin',h.url('admin_home'))}
19 19 </%def>
20 20 <%def name="page_nav()">
21 21 <li>${h.link_to(u'Home',h.url('/'))}</li>
22 22 <li class="current">${_('Admin')}</li>
23 23 </%def>
24 24 <%def name="main()">
25 25 %if c.admin_user:
26 26 <ul class="submenu">
27 27 <li>
28 ${h.link_to(u'Repos managment',h.url('admin_repos_manage'))}
28 ${h.link_to(u'Repos',h.url('repos'))}
29 29 </li>
30 30 <li>
31 ${h.link_to(u'Users managment',h.url('admin_users_manage'))}
31 ${h.link_to(u'Users',h.url('users'))}
32 32 </li>
33 33 </ul>
34 34 <br/>
35 35 <div>
36 36
37 37 <h2>Hi !</h2>
38 38 </div>
39 39 %else:
40 40 <div>
41 41 <br />
42 42 <h2>${_('Login')}</h2>
43 43 ${h.form(h.url.current())}
44 44 <table>
45 45 <tr>
46 46 <td>${_('Username')}</td>
47 47 <td>${h.text('username')}</td>
48 48 <td>${get_form_error('username')} </td>
49 49 </tr>
50 50 <tr>
51 51 <td>${_('Password')}</td>
52 52 <td>${h.password('password')}</td>
53 53 <td>${get_form_error('password')}</td>
54 54 </tr>
55 55 <tr>
56 56 <td></td>
57 57 <td>${h.submit('login','login')}</td>
58 58 </tr>
59 59 </table>
60 60 ${h.end_form()}
61 61 </div>
62 62 %endif
63 63
64 64 </%def> No newline at end of file
@@ -1,40 +1,28 b''
1 1 <%inherit file="base/base.html"/>
2 2 <%def name="title()">
3 3 ${_('Repository managment')}
4 4 </%def>
5 5 <%def name="breadcrumbs()">
6 6 ${h.link_to(u'Home',h.url('/'))}
7 7 /
8 8 ${h.link_to(u'Admin',h.url('admin_home'))}
9 9 /
10 ${h.link_to(u'Repos managment',h.url('admin_repos_manage'))}
10 ${h.link_to(u'Repos managment',h.url('repos'))}
11 11 </%def>
12 12 <%def name="page_nav()">
13 13 <li>${h.link_to(u'Home',h.url('/'))}</li>
14 14 <li class="current">${_('Admin')}</li>
15 15 </%def>
16 16 <%def name="main()">
17
18
19 <div class="twocol-form">
20 <h2>Create new repository</h2>
21 <form method="post" action="/repo/create/">
22 <table>
23 <tbody><tr><th><label for="id_name">Name:</label></th><td><input type="text" maxlength="255" name="name" id="id_name"></td></tr>
24 <tr><th><label for="id_description">Description:</label></th><td><textarea name="description" cols="40" rows="10" id="id_description"></textarea></td></tr>
25 <tr><th><label for="id_website">Website:</label></th><td><input type="text" maxlength="128" name="website" id="id_website"></td></tr>
26 <tr><th><label for="id_is_private">Private:</label></th><td><input type="checkbox" id="id_is_private" name="is_private"></td></tr>
27 <tr><th><label for="id_has_issues">Issue tracking:</label></th><td><input type="checkbox" id="id_has_issues" name="has_issues" checked="checked"></td></tr>
28 <tr><th><label for="id_has_wiki">Wiki:</label></th><td><input type="checkbox" id="id_has_wiki" name="has_wiki" checked="checked"></td></tr>
29
30
31 <tr><td colspan="2">&nbsp;</td></tr>
32 <tr>
33 <td colspan="2">
34 <input type="submit" class="primary-button" value="Create repository"> <input type="reset" onclick="document.location='http://bitbucket.org/';" class="secondary-button secondary-button-darkbg" value="Cancel">
35 </td>
36 </tr>
37 </tbody></table>
38 </form>
17 <ul class="submenu">
18 <li class="current_submenu">
19 ${h.link_to(u'Repos',h.url('repos'))}
20 </li>
21 <li>
22 ${h.link_to(u'Users',h.url('users'))}
23 </li>
24 </ul>
25 <div>
26 <h2>${_('Mercurial repos')}</h2>
39 27 </div>
40 28 </%def> No newline at end of file
@@ -1,34 +1,47 b''
1 1 <%inherit file="base/base.html"/>
2 2 <%def name="title()">
3 3 ${_('Repository managment')}
4 4 </%def>
5 5 <%def name="breadcrumbs()">
6 6 ${h.link_to(u'Home',h.url('/'))}
7 7 /
8 8 ${h.link_to(u'Admin',h.url('admin_home'))}
9 9 /
10 ${h.link_to(u'Users managment',h.url('admin_users_manage'))}
10 ${h.link_to(u'Users managment',h.url('users'))}
11 11 </%def>
12 12 <%def name="page_nav()">
13 13 <li>${h.link_to(u'Home',h.url('/'))}</li>
14 14 <li class="current">${_('Admin')}</li>
15 15 </%def>
16 16 <%def name="main()">
17
17 <ul class="submenu">
18 <li>
19 ${h.link_to(u'Repos',h.url('repos'))}
20 </li>
21 <li class="current_submenu">
22 ${h.link_to(u'Users',h.url('users'))}
23 </li>
24 </ul>
25 <div>
26 <h2>${_('Mercurial users')}</h2>
18 27 <table cellspacing="0">
19 28 <tr>
20 29 <th>Id</th>
21 30 <th>Username</th>
22 31 <th>Password</th>
23 32 <th>Active</th>
33 <th>Admin</th>
24 34 </tr>
25 35 %for i in c.users_list:
26 36 <tr>
27 37 <td>${i[0]}</td>
28 38 <td>${i[1]}</td>
29 39 <td>${i[2]}</td>
30 40 <td>${i[3]}</td>
41 <td>${i[4]}</td>
31 42 </tr>
32 43 %endfor
33 44 </table>
45 </div>
46
34 47 </%def> No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now