Merge branch 'master' into request_form_styles
This commit is contained in:
33
atst/app.py
33
atst/app.py
@@ -4,12 +4,13 @@ import tornado.web
|
||||
from tornado.web import url
|
||||
from redis import StrictRedis
|
||||
|
||||
from atst.handlers.main import MainHandler
|
||||
from atst.handlers.home import Home
|
||||
from atst.handlers.login import Login
|
||||
from atst.handlers.main import Main
|
||||
from atst.handlers.root import Root
|
||||
from atst.handlers.login_redirect import LoginRedirect
|
||||
from atst.handlers.workspace import Workspace
|
||||
from atst.handlers.request import Request
|
||||
from atst.handlers.request_new import RequestNew
|
||||
from atst.handlers.request_submit import RequestsSubmit
|
||||
from atst.handlers.dev import Dev
|
||||
from atst.home import home
|
||||
from atst.api_client import ApiClient
|
||||
@@ -21,23 +22,23 @@ ENV = os.getenv("TORNADO_ENV", "dev")
|
||||
def make_app(config, deps, **kwargs):
|
||||
|
||||
routes = [
|
||||
url(r"/", Home, {"page": "login"}, name="main"),
|
||||
url(r"/", Root, {"page": "root"}, name="root"),
|
||||
url(
|
||||
r"/login",
|
||||
Login,
|
||||
r"/login-redirect",
|
||||
LoginRedirect,
|
||||
{"sessions": deps["sessions"], "authnid_client": deps["authnid_client"]},
|
||||
name="login",
|
||||
name="login_redirect",
|
||||
),
|
||||
url(r"/home", MainHandler, {"page": "home"}, name="home"),
|
||||
url(r"/home", Main, {"page": "home"}, name="home"),
|
||||
url(
|
||||
r"/styleguide",
|
||||
MainHandler,
|
||||
Main,
|
||||
{"page": "styleguide"},
|
||||
name="styleguide",
|
||||
),
|
||||
url(
|
||||
r"/workspaces/blank",
|
||||
MainHandler,
|
||||
Main,
|
||||
{"page": "workspaces_blank"},
|
||||
name="workspaces_blank",
|
||||
),
|
||||
@@ -71,9 +72,15 @@ def make_app(config, deps, **kwargs):
|
||||
{"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"),
|
||||
url(r"/calculator", MainHandler, {"page": "calculator"}, name="calculator"),
|
||||
url(
|
||||
r"/requests/submit/(\S+)",
|
||||
RequestsSubmit,
|
||||
{"requests_client": deps["requests_client"]},
|
||||
name="requests_submit",
|
||||
),
|
||||
url(r"/users", Main, {"page": "users"}, name="users"),
|
||||
url(r"/reports", Main, {"page": "reports"}, name="reports"),
|
||||
url(r"/calculator", Main, {"page": "calculator"}, name="calculator"),
|
||||
]
|
||||
|
||||
if not ENV == "production":
|
||||
|
@@ -15,10 +15,14 @@ class FinancialForm(Form):
|
||||
"Unique Item Identifier (UII)s related to your application(s) if you already have them."
|
||||
)
|
||||
|
||||
pe_id = NewlineListField(
|
||||
"Program Element (PE) Numbers related to your request"
|
||||
pe_id = StringField(
|
||||
"Program Element (PE) Number related to your request"
|
||||
)
|
||||
|
||||
treasury_code = StringField("Please provide your Program Treasury Code")
|
||||
|
||||
ba_code = StringField("Please provide your Program BA Code")
|
||||
|
||||
fname_co = StringField("Contracting Officer First Name", validators=[Required()])
|
||||
lname_co = StringField("Contracting Officer Last Name", validators=[Required()])
|
||||
|
||||
|
@@ -2,7 +2,7 @@ from wtforms.fields.html5 import IntegerField
|
||||
from wtforms.fields import RadioField, StringField, TextAreaField
|
||||
from wtforms.validators import NumberRange, InputRequired
|
||||
from wtforms_tornado import Form
|
||||
from .fields import DateField, NewlineListField
|
||||
from .fields import DateField
|
||||
from .validators import DateRange
|
||||
import pendulum
|
||||
|
||||
|
@@ -23,6 +23,7 @@ class BaseHandler(tornado.web.RequestHandler):
|
||||
try:
|
||||
session = self.application.sessions.get_session(cookie)
|
||||
except SessionNotFoundError:
|
||||
self.clear_cookie("atat")
|
||||
return None
|
||||
else:
|
||||
return None
|
||||
|
@@ -2,7 +2,7 @@ import tornado
|
||||
from atst.handler import BaseHandler
|
||||
|
||||
|
||||
class Login(BaseHandler):
|
||||
class LoginRedirect(BaseHandler):
|
||||
def initialize(self, authnid_client, sessions):
|
||||
self.authnid_client = authnid_client
|
||||
self.sessions = sessions
|
@@ -2,7 +2,7 @@ import tornado
|
||||
from atst.handler import BaseHandler
|
||||
|
||||
|
||||
class MainHandler(BaseHandler):
|
||||
class Main(BaseHandler):
|
||||
def initialize(self, page):
|
||||
self.page = page
|
||||
|
||||
|
@@ -1,43 +1,15 @@
|
||||
import tornado
|
||||
from collections import defaultdict
|
||||
|
||||
from atst.handler import BaseHandler
|
||||
from atst.forms.request import RequestForm
|
||||
from atst.forms.org import OrgForm
|
||||
from atst.forms.poc import POCForm
|
||||
from atst.forms.review import ReviewForm
|
||||
from atst.forms.financial import FinancialForm
|
||||
import tornado.httputil
|
||||
|
||||
|
||||
class RequestNew(BaseHandler):
|
||||
screens = [
|
||||
{
|
||||
"title": "Details of Use",
|
||||
"section": "details_of_use",
|
||||
"form": RequestForm,
|
||||
"subitems": [
|
||||
{"title": "Overall request details", "id": "overall-request-details"},
|
||||
{"title": "Cloud Resources", "id": "cloud-resources"},
|
||||
{"title": "Support Staff", "id": "support-staff"},
|
||||
],
|
||||
},
|
||||
{
|
||||
"title": "Information About You",
|
||||
"section": "information_about_you",
|
||||
"form": OrgForm,
|
||||
},
|
||||
{
|
||||
"title": "Primary Point of Contact",
|
||||
"section": "primary_poc",
|
||||
"form": POCForm,
|
||||
},
|
||||
{"title": "Review & Submit", "section": "review_submit", "form": ReviewForm},
|
||||
{
|
||||
"title": "Financial Verification",
|
||||
"section": "financial_verification",
|
||||
"form": FinancialForm,
|
||||
},
|
||||
]
|
||||
|
||||
def initialize(self, page, requests_client):
|
||||
self.page = page
|
||||
self.requests_client = requests_client
|
||||
@@ -47,58 +19,62 @@ class RequestNew(BaseHandler):
|
||||
def post(self, screen=1, request_id=None):
|
||||
self.check_xsrf_cookie()
|
||||
screen = int(screen)
|
||||
form_metadata = self.screens[screen - 1]
|
||||
form_section = form_metadata["section"]
|
||||
form = form_metadata["form"](self.request.arguments)
|
||||
post_data = self.request.arguments
|
||||
jedi_flow = JEDIRequestFlow(
|
||||
self.requests_client, screen, post_data=post_data, request_id=request_id
|
||||
)
|
||||
|
||||
if form.validate():
|
||||
response = yield self.create_or_update_request(
|
||||
form_section, form.data, request_id
|
||||
)
|
||||
if jedi_flow.validate():
|
||||
response = yield jedi_flow.create_or_update_request(self.get_current_user())
|
||||
if response.ok:
|
||||
where = self.application.default_router.reverse_url(
|
||||
"request_form_update",
|
||||
str(screen + 1),
|
||||
request_id or response.json["id"],
|
||||
"request_form_update", str(screen + 1), jedi_flow.request_id
|
||||
)
|
||||
self.redirect(where)
|
||||
else:
|
||||
self.set_status(response.code)
|
||||
else:
|
||||
self.show_form(screen, form)
|
||||
self.render(
|
||||
"requests/screen-%d.html.to" % int(screen),
|
||||
f=jedi_flow.form,
|
||||
data=post_data,
|
||||
page=self.page,
|
||||
screens=jedi_flow.screens,
|
||||
current=screen,
|
||||
next_screen=jedi_flow.next_screen,
|
||||
request_id=jedi_flow.request_id,
|
||||
)
|
||||
|
||||
@tornado.web.authenticated
|
||||
@tornado.gen.coroutine
|
||||
def get(self, screen=1, request_id=None):
|
||||
form = None
|
||||
form_data = None
|
||||
is_review_section = screen == 4
|
||||
screen = int(screen)
|
||||
request = None
|
||||
|
||||
if request_id:
|
||||
request = yield self.get_request(request_id)
|
||||
if request.ok:
|
||||
if is_review_section:
|
||||
form_data = request.json["body"]
|
||||
else:
|
||||
form_metadata = self.screens[int(screen) - 1]
|
||||
section = form_metadata["section"]
|
||||
form_data = request.json["body"].get(section, request.json["body"])
|
||||
form = form_metadata["form"](data=form_data)
|
||||
response = yield self.requests_client.get(
|
||||
"/users/{}/requests/{}".format(
|
||||
self.get_current_user()["id"], request_id
|
||||
),
|
||||
raise_error=False,
|
||||
)
|
||||
if response.ok:
|
||||
request = response.json
|
||||
|
||||
self.show_form(screen=screen, form=form, request_id=request_id, data=form_data)
|
||||
jedi_flow = JEDIRequestFlow(
|
||||
self.requests_client, screen, request, request_id=request_id
|
||||
)
|
||||
|
||||
def show_form(self, screen=1, form=None, request_id=None, data=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,
|
||||
data=data,
|
||||
f=jedi_flow.form,
|
||||
data=jedi_flow.current_step_data,
|
||||
page=self.page,
|
||||
screens=self.screens,
|
||||
current=int(screen),
|
||||
next_screen=int(screen) + 1,
|
||||
screens=jedi_flow.screens,
|
||||
current=screen,
|
||||
next_screen=screen + 1,
|
||||
request_id=request_id,
|
||||
can_submit=jedi_flow.can_submit
|
||||
)
|
||||
|
||||
@tornado.gen.coroutine
|
||||
@@ -109,16 +85,128 @@ class RequestNew(BaseHandler):
|
||||
)
|
||||
return request
|
||||
|
||||
|
||||
class JEDIRequestFlow(object):
|
||||
def __init__(
|
||||
self,
|
||||
requests_client,
|
||||
current_step,
|
||||
request=None,
|
||||
post_data=None,
|
||||
request_id=None,
|
||||
):
|
||||
self.requests_client = requests_client
|
||||
|
||||
self.current_step = current_step
|
||||
self.request = request
|
||||
|
||||
self.post_data = post_data
|
||||
self.is_post = self.post_data is not None
|
||||
|
||||
self.request_id = request_id
|
||||
self.form = self._form()
|
||||
|
||||
def _form(self):
|
||||
if self.is_post:
|
||||
return self.form_class()(self.post_data)
|
||||
elif self.request:
|
||||
return self.form_class()(data=self.current_step_data)
|
||||
else:
|
||||
return self.form_class()()
|
||||
|
||||
def validate(self):
|
||||
return self.form.validate()
|
||||
|
||||
@property
|
||||
def current_screen(self):
|
||||
return self.screens[self.current_step - 1]
|
||||
|
||||
@property
|
||||
def form_section(self):
|
||||
return self.current_screen["section"]
|
||||
|
||||
def form_class(self):
|
||||
return self.current_screen["form"]
|
||||
|
||||
@property
|
||||
def current_step_data(self):
|
||||
data = {}
|
||||
|
||||
if self.is_post:
|
||||
data = self.post_data
|
||||
|
||||
if self.request:
|
||||
if self.form_section == "review_submit":
|
||||
data = self.request["body"]
|
||||
else:
|
||||
data = self.request["body"].get(self.form_section, {})
|
||||
|
||||
return defaultdict(lambda: defaultdict(lambda: 'Input required'), data)
|
||||
|
||||
@property
|
||||
def can_submit(self):
|
||||
return self.request and self.request["status"] != "incomplete"
|
||||
|
||||
@property
|
||||
def next_screen(self):
|
||||
return self.current_step + 1
|
||||
|
||||
@property
|
||||
def screens(self):
|
||||
return [
|
||||
{
|
||||
"title": "Details of Use",
|
||||
"section": "details_of_use",
|
||||
"form": RequestForm,
|
||||
"subitems": [
|
||||
{
|
||||
"title": "Overall request details",
|
||||
"id": "overall-request-details",
|
||||
},
|
||||
{"title": "Cloud Resources", "id": "cloud-resources"},
|
||||
{"title": "Support Staff", "id": "support-staff"},
|
||||
],
|
||||
"show": True,
|
||||
},
|
||||
{
|
||||
"title": "Information About You",
|
||||
"section": "information_about_you",
|
||||
"form": OrgForm,
|
||||
"show": True,
|
||||
},
|
||||
{
|
||||
"title": "Primary Point of Contact",
|
||||
"section": "primary_poc",
|
||||
"form": POCForm,
|
||||
"show": True,
|
||||
},
|
||||
{
|
||||
"title": "Review & Submit",
|
||||
"section": "review_submit",
|
||||
"form": ReviewForm,
|
||||
"show":True,
|
||||
},
|
||||
{
|
||||
"title": "Financial Verification",
|
||||
"section": "financial_verification",
|
||||
"form": FinancialForm,
|
||||
"show": self.request and self.request["status"] == "approved",
|
||||
},
|
||||
]
|
||||
|
||||
@tornado.gen.coroutine
|
||||
def create_or_update_request(self, form_section, form_data, request_id=None):
|
||||
def create_or_update_request(self, user):
|
||||
request_data = {
|
||||
"creator_id": self.get_current_user()["id"],
|
||||
"request": {form_section: form_data},
|
||||
"creator_id": user["id"],
|
||||
"request": {self.form_section: self.form.data},
|
||||
}
|
||||
if request_id:
|
||||
if self.request_id:
|
||||
response = yield self.requests_client.patch(
|
||||
"/requests/{}".format(request_id), json=request_data
|
||||
"/requests/{}".format(self.request_id), json=request_data
|
||||
)
|
||||
else:
|
||||
response = yield self.requests_client.post("/requests", json=request_data)
|
||||
self.request = response.json
|
||||
self.request_id = self.request["id"]
|
||||
|
||||
return response
|
||||
|
17
atst/handlers/request_submit.py
Normal file
17
atst/handlers/request_submit.py
Normal file
@@ -0,0 +1,17 @@
|
||||
import tornado
|
||||
|
||||
from atst.handler import BaseHandler
|
||||
|
||||
|
||||
class RequestsSubmit(BaseHandler):
|
||||
def initialize(self, requests_client):
|
||||
self.requests_client = requests_client
|
||||
|
||||
@tornado.web.authenticated
|
||||
@tornado.gen.coroutine
|
||||
def post(self, request_id):
|
||||
yield self.requests_client.post(
|
||||
"/requests/{}/submit".format(request_id),
|
||||
allow_nonstandard_methods=True
|
||||
)
|
||||
self.redirect("/requests")
|
@@ -1,7 +1,7 @@
|
||||
from atst.handler import BaseHandler
|
||||
|
||||
|
||||
class Home(BaseHandler):
|
||||
class Root(BaseHandler):
|
||||
def initialize(self, page):
|
||||
self.page = page
|
||||
|
Reference in New Issue
Block a user