diff --git a/atst/api_client.py b/atst/api_client.py index 5b720244..f1b39c0f 100644 --- a/atst/api_client.py +++ b/atst/api_client.py @@ -22,6 +22,10 @@ class ApiClient(object): def post(self, path, **kwargs): return (yield self.make_request('POST', self.base_url + path, **kwargs)) + @tornado.gen.coroutine + def patch(self, path, **kwargs): + return (yield self.make_request('PATCH', self.base_url + path, **kwargs)) + @tornado.gen.coroutine def delete(self, path, **kwargs): return (yield self.make_request('DELETE', self.base_url + path, **kwargs)) @@ -39,11 +43,13 @@ class ApiClient(object): if not 'validate_cert' in kwargs: kwargs['validate_cert'] = self.validate_cert - response = yield self.client.fetch(url, method=method, **kwargs) + response = yield self.client.fetch( + url, method=method, **kwargs) return self.adapt_response(response) def adapt_response(self, response): - if response.headers['Content-Type'] == 'application/json': + if 'application/json' in response.headers['Content-Type']: json = loads(response.body) setattr(response, 'json', json) + setattr(response, 'ok', 200 <= response.code < 300) return response diff --git a/atst/app.py b/atst/app.py index 67807122..c42b7aae 100644 --- a/atst/app.py +++ b/atst/app.py @@ -34,7 +34,11 @@ def make_app(config, deps, **kwargs): {"page": "workspaces", "authz_client": deps["authz_client"]}, name="workspaces", ), - url(r"/requests", Request, {"page": "requests"}, name="requests"), + url( + r"/requests", + Request, + {"page": "requests", 'requests_client': deps['requests_client']}, + name="requests"), url( r"/requests/new", RequestNew, @@ -44,7 +48,13 @@ def make_app(config, deps, **kwargs): r"/requests/new/([0-9])", RequestNew, {"page": "requests_new", "requests_client": deps["requests_client"]}, - name="request_form", + name="request_form_new", + ), + url( + r"/requests/new/([0-9])/(\S+)", + RequestNew, + {"page": "requests_new", "requests_client": deps["requests_client"]}, + name="request_form_update", ), url(r"/users", MainHandler, {"page": "users"}, name="users"), url(r"/reports", MainHandler, {"page": "reports"}, name="reports"), diff --git a/atst/forms/request.py b/atst/forms/request.py index 31e189ad..eae0e0a9 100644 --- a/atst/forms/request.py +++ b/atst/forms/request.py @@ -1,5 +1,5 @@ from wtforms.fields.html5 import IntegerField -from wtforms.fields import RadioField, StringField, SelectField, TextAreaField +from wtforms.fields import RadioField, StringField, SelectField, TextAreaField, FormField from wtforms.validators import Required, ValidationError from wtforms_tornado import Form from .date import DateForm @@ -14,7 +14,7 @@ class RequestForm(Form): ('B','Option B'), ('C','Option C') ]) # no way to apply a label to a whole nested form like this - date_start = DateForm() + date_start = FormField(DateForm) period_of_performance = SelectField('Desired period of performance', validators=[Required()], choices=[('','- Select -'), ('value1','30 days'), @@ -31,6 +31,12 @@ class RequestForm(Form): ('both', 'Both') ]) number_of_cores = IntegerField('Number of cores', validators=[Required()]) total_ram = IntegerField('Total RAM', validators=[Required()]) + object_storage = IntegerField('Total object storage', validators=[Required()]) + server_storage = IntegerField('Total server storage', validators=[Required()]) + total_active_users = IntegerField('Total active users', validators=[Required()]) + total_peak_users = IntegerField('Total peak users', validators=[Required()]) + total_requests = IntegerField('Total requests', validators=[Required()]) + total_environments = IntegerField('Total environments', validators=[Required()]) # this is just an example validation; obviously this is wrong. def validate_total_ram(self,field): diff --git a/atst/handler.py b/atst/handler.py index afe80fa8..011ae3e6 100644 --- a/atst/handler.py +++ b/atst/handler.py @@ -26,7 +26,7 @@ class BaseHandler(tornado.web.RequestHandler): def get_current_user(self): if self.get_secure_cookie('atst'): - return True + return '9cb348f0-8102-4962-88c4-dac8180c904c' else: return False diff --git a/atst/handlers/request.py b/atst/handlers/request.py index 9ce3da34..3636ae64 100644 --- a/atst/handlers/request.py +++ b/atst/handlers/request.py @@ -28,10 +28,27 @@ mock_requests = [ }, ] +def map_request(request): + return { + 'order_id': request['id'], + 'is_new': False, + 'status': 'Pending', + 'app_count': 1, + 'is_new': False, + 'date': '', + 'full_name': 'Richard Howard' + } + class Request(BaseHandler): - def initialize(self, page): + def initialize(self, page, requests_client): self.page = page + self.requests_client = requests_client @tornado.web.authenticated + @tornado.gen.coroutine def get(self): - self.render('requests.html.to', page = self.page, requests = mock_requests ) + response = yield self.requests_client.get( + '/users/{}/requests'.format(self.get_current_user())) + requests = response.json['requests'] + mapped_requests = [map_request(request) for request in requests] + self.render('requests.html.to', page=self.page, requests=mapped_requests) diff --git a/atst/handlers/request_new.py b/atst/handlers/request_new.py index 5b5f7f40..93ee57c8 100644 --- a/atst/handlers/request_new.py +++ b/atst/handlers/request_new.py @@ -6,6 +6,7 @@ from atst.forms.funding import FundingForm from atst.forms.readiness import ReadinessForm from atst.forms.review import ReviewForm import tornado.httputil +from tornado.httpclient import HTTPError class RequestNew(BaseHandler): @@ -45,26 +46,62 @@ class RequestNew(BaseHandler): self.requests_client = requests_client @tornado.web.authenticated - def post(self, screen = 1): + @tornado.gen.coroutine + def post(self, screen=1, request_id=None): self.check_xsrf_cookie() screen = int(screen) form = self.screens[ screen - 1 ]['form'](self.request.arguments) if form.validate(): - where = self.application.default_router.reverse_url('request_form', str(screen + 1)) - self.redirect(where) + response = yield self.create_or_update_request(form.data, request_id) + if response.ok: + where = self.application.default_router.reverse_url( + 'request_form_update', str(screen + 1), request_id or response.json['id']) + self.redirect(where) + else: + self.set_status(response.code) else: self.show_form(screen, form) @tornado.web.authenticated - def get(self, screen = 1): - self.show_form(screen=screen) + @tornado.gen.coroutine + def get(self, screen=1, request_id=None): + form = None + if request_id: + request = yield self.get_request(request_id) + if request.ok: + form_data = request.json['body'] if request else {} + form = self.screens[ int(screen) - 1 ]['form'](data=form_data) - def show_form(self, screen = 1, form = None): + self.show_form(screen=screen, form=form, request_id=request_id) + + def show_form(self, screen=1, form=None, request_id=None): if not form: form = self.screens[ int(screen) - 1 ]['form'](self.request.arguments) - self.render( 'requests/screen-%d.html.to' % int(screen), - f = form, - page = self.page, - screens = self.screens, - current = int(screen), - next_screen = int(screen) + 1 ) + self.render('requests/screen-%d.html.to' % int(screen), + f=form, + page=self.page, + screens=self.screens, + current=int(screen), + next_screen=int(screen) + 1, + request_id=request_id) + + @tornado.gen.coroutine + def get_request(self, request_id): + request = yield self.requests_client.get( + '/users/{}/requests/{}'.format(self.get_current_user(), request_id), + raise_error=False) + return request + + @tornado.gen.coroutine + def create_or_update_request(self, form_data, request_id=None): + request_data = { + 'creator_id': self.get_current_user(), + 'request': form_data + } + if request_id: + response = yield self.requests_client.patch( + '/requests/{}'.format(request_id), json=request_data) + else: + response = yield self.requests_client.post( + '/requests', json=request_data) + return response diff --git a/templates/requests.html.to b/templates/requests.html.to index 0c5fe1cf..431d9175 100644 --- a/templates/requests.html.to +++ b/templates/requests.html.to @@ -20,7 +20,7 @@
{% for r in requests %}Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus error omnis a, tenetur similique quo officiis voluptates eum recusandae dolorem minus dignissimos, magni consequatur, maxime debitis reprehenderit sint non iusto?
-New Application -Existing Application -Sandbox Environment +New Application +Existing Application +Sandbox Environment -{% end %} \ No newline at end of file +{% end %} diff --git a/templates/requests/screen-1.html.to b/templates/requests/screen-1.html.to index caa6e5b8..5c9149fc 100644 --- a/templates/requests/screen-1.html.to +++ b/templates/requests/screen-1.html.to @@ -92,29 +92,25 @@The particulars of your body copy will be determined by the topic of your page. Regardless of topic, it’s a good practice to follow the inverted pyramid structure when writing copy: Begin with the information that’s most important to your users and then present information of less importance.
- - - - - - + {{ f.object_storage.label }} + {{ f.object_storage(placeholder="Total object storage") }} + {{ f.server_storage.label }} + {{ f.server_storage(placeholder="Total server storage") }}The particulars of your body copy will be determined by the topic of your page. Regardless of topic, it’s a good practice to follow the inverted pyramid structure when writing copy: Begin with the information that’s most important to your users and then present information of less importance.
- - + {{ f.total_active_users.label }} + {{ f.total_active_users(placeholder="Total active users") }} - - - - - - - - + {{ f.total_peak_users.label }} + {{ f.total_peak_users(placeholder="Total peak users") }} + {{ f.total_requests.label }} + {{ f.total_requests(placeholder="Total requests") }} + {{ f.total_environments.label }} + {{ f.total_environments(placeholder="Total number of environments") }} {% end %} diff --git a/templates/requests/sidebar.html.to b/templates/requests/sidebar.html.to index 9b77acf0..6543fa2c 100644 --- a/templates/requests/sidebar.html.to +++ b/templates/requests/sidebar.html.to @@ -2,7 +2,7 @@ {% for i,s in enumerate(screens) %}