diff --git a/atst/domain/projects.py b/atst/domain/projects.py index d3b2848a..611ee2f9 100644 --- a/atst/domain/projects.py +++ b/atst/domain/projects.py @@ -1,6 +1,9 @@ from atst.database import db -from atst.models.project import Project +from atst.domain.authz import Authorization from atst.domain.environments import Environments +from atst.domain.exceptions import NotFoundError +from atst.models.permissions import Permissions +from atst.models.project import Project class Projects(object): @@ -13,3 +16,20 @@ class Projects(object): db.session.commit() return project + + @classmethod + def get(cls, user, workspace, project_id): + # TODO: this should check permission for this particular project + Authorization.check_workspace_permission( + user, + workspace, + Permissions.VIEW_APPLICATION_IN_WORKSPACE, + "view project in workspace", + ) + + try: + project = db.session.query(Project).filter_by(id=project_id).one() + except NoResultFound: + raise NotFoundError("project") + + return project diff --git a/atst/routes/requests/index.py b/atst/routes/requests/index.py index b475a9e6..fe3e894e 100644 --- a/atst/routes/requests/index.py +++ b/atst/routes/requests/index.py @@ -98,4 +98,4 @@ class RequestsIndex(object): @requests_bp.route("/requests", methods=["GET"]) def requests_index(): context = RequestsIndex(g.current_user).execute() - return render_template("requests.html", **context) + return render_template("requests/index.html", **context) diff --git a/atst/routes/workspaces.py b/atst/routes/workspaces.py index d6da53ab..0e18ed63 100644 --- a/atst/routes/workspaces.py +++ b/atst/routes/workspaces.py @@ -47,13 +47,13 @@ def workspace(): @bp.route("/workspaces") def workspaces(): workspaces = Workspaces.get_many(g.current_user) - return render_template("workspaces.html", page=5, workspaces=workspaces) + return render_template("workspaces/index.html", page=5, workspaces=workspaces) @bp.route("/workspaces//projects") def workspace_projects(workspace_id): workspace = Workspaces.get(g.current_user, workspace_id) - return render_template("workspace_projects.html", workspace=workspace) + return render_template("workspaces/projects/index.html", workspace=workspace) @bp.route("/workspaces/") @@ -64,7 +64,7 @@ def show_workspace(workspace_id): @bp.route("/workspaces//members") def workspace_members(workspace_id): workspace = Workspaces.get(g.current_user, workspace_id) - return render_template("workspace_members.html", workspace=workspace) + return render_template("workspaces/members/index.html", workspace=workspace) @bp.route("/workspaces//reports") @@ -86,7 +86,7 @@ def workspace_reports(workspace_id): two_months_ago = prev_month - timedelta(days=28) return render_template( - "workspace_reports.html", + "workspaces/reports/index.html", workspace_totals=Reports.workspace_totals(alternate_reports), monthly_totals=Reports.monthly_totals(alternate_reports), current_month=current_month, @@ -99,11 +99,13 @@ def workspace_reports(workspace_id): def new_project(workspace_id): workspace = Workspaces.get_for_update(g.current_user, workspace_id) form = NewProjectForm() - return render_template("workspace_project_new.html", workspace=workspace, form=form) + return render_template( + "workspaces/projects/new.html", workspace=workspace, form=form + ) @bp.route("/workspaces//projects/new", methods=["POST"]) -def update_project(workspace_id): +def create_project(workspace_id): workspace = Workspaces.get_for_update(g.current_user, workspace_id) form = NewProjectForm(http_request.form) @@ -120,15 +122,32 @@ def update_project(workspace_id): ) else: return render_template( - "workspace_project_new.html", workspace=workspace, form=form + "workspaces/projects/new.html", workspace=workspace, form=form ) +@bp.route("/workspaces//projects//edit") +def edit_project(workspace_id, project_id): + workspace = Workspaces.get_for_update(g.current_user, workspace_id) + project = Projects.get(g.current_user, workspace, project_id) + form = NewProjectForm( + name=project.name, + environment_names=[env.name for env in project.environments], + description=project.description, + ) + + return render_template( + "workspaces/projects/edit.html", workspace=workspace, project=project, form=form + ) + + @bp.route("/workspaces//members/new") def new_member(workspace_id): workspace = Workspaces.get(g.current_user, workspace_id) form = NewMemberForm() - return render_template("member_new.html", workspace=workspace, form=form) + return render_template( + "workspaces/members/new.html", workspace=workspace, form=form + ) @bp.route("/workspaces//members/new", methods=["POST"]) @@ -146,7 +165,9 @@ def create_member(workspace_id): ) ) else: - return render_template("member_new.html", workspace=workspace, form=form) + return render_template( + "workspaces/members/new.html", workspace=workspace, form=form + ) @bp.route("/workspaces//members//member_edit") @@ -161,7 +182,7 @@ def view_member(workspace_id, member_id): member = WorkspaceUsers.get(workspace_id, member_id) form = EditMemberForm(workspace_role=member.role) return render_template( - "member_edit.html", form=form, workspace=workspace, member=member + "workspaces/members/edit.html", form=form, workspace=workspace, member=member ) @@ -195,5 +216,8 @@ def update_member(workspace_id, member_id): ) else: return render_template( - "member_edit.html", form=form, workspace=workspace, member=member + "workspaces/members/edit.html", + form=form, + workspace=workspace, + member=member, ) diff --git a/templates/workspace_project_new.html b/templates/fragments/edit_project_form.html similarity index 78% rename from templates/workspace_project_new.html rename to templates/fragments/edit_project_form.html index 2a7d0a27..6858604a 100644 --- a/templates/workspace_project_new.html +++ b/templates/fragments/edit_project_form.html @@ -1,30 +1,20 @@ {% from "components/icon.html" import Icon %} {% from "components/modal.html" import Modal %} {% from "components/text_input.html" import TextInput %} -{% from "components/tooltip.html" import Tooltip %} {% from "components/alert.html" import Alert %} -{% extends "base_workspace.html" %} - -{% block workspace_content %} - -{% set modalName = "newProjectConfirmation" %} -{% if request.args.get("newWorkspace") %} - {{ Alert('Workspace created!', - message="\ -

You are now ready to create projects and environments within the JEDI Cloud.

- ", - level='success' - ) }} -{% endif %} - -
+ {% set new_project = project is not defined %} + {% set form_action = url_for('workspaces.create_project', workspace_id=workspace.id) if new_project else url_for('workspaces.edit_project', workspace_id=workspace.id, project_id=project.id) %} + {% set action_text = 'Create' if new_project else 'Update' %} + {% set title_text = 'Add a new project' if new_project else 'Edit {} project'.format(project.name) %} + + {% call Modal(name=modalName, dismissable=False) %} -

Create project !{ name }

+

{{ action_text }} project !{ name }

- When you click Create Project, the environments + When you click {{ action_text }} Project, the environments !{environment.name} @@ -32,7 +22,7 @@

- +
{% endcall %} @@ -40,7 +30,7 @@ {{ form.csrf_token }}
-

Add a new project

+

{{ title_text }}

@@ -86,11 +76,11 @@
- +
-{% endblock %} + diff --git a/templates/project_edit.html.to b/templates/project_edit.html.to deleted file mode 100644 index 58c18bed..00000000 --- a/templates/project_edit.html.to +++ /dev/null @@ -1,108 +0,0 @@ -{% extends "base_workspace.html.to" %} - -{% from "components/alert.html" import Alert %} - -{% block template_vars %} - {% set is_new_project = False %} - {% set project_name = "Code.mil" %} - {% set project_id = "789" %} -{% end %} - -{% block workspace_content %} - -{{ Alert( - "UI Mock", - message="

Please note, this screen is a non-functional UI mockup.

", - level="warning" -) }} - -
-
-
-

- {% if is_new_project %} - Add a new project - {% else %} - {{ project_name }} - Edit project - {% end %} -

-
- -
-
- - -
- -
- - -
-
-
- -
-
-

Project Environments

-
- - {# All instances of .usa-input groups here should be replaced with {% module TextInput(wtforms.fields.Field) %} #} - -
    -
  • -
    - - -
    - -
  • - -
  • -
    - - -
    - -
  • - -
  • -
    - - -
    - -
  • - -
- - -
- - -
- -{% end %} - diff --git a/templates/requests_new.html b/templates/requests/_new.html similarity index 100% rename from templates/requests_new.html rename to templates/requests/_new.html diff --git a/templates/request_approval.html b/templates/requests/approval.html similarity index 100% rename from templates/request_approval.html rename to templates/requests/approval.html diff --git a/templates/requests.html b/templates/requests/index.html similarity index 100% rename from templates/requests.html rename to templates/requests/index.html diff --git a/templates/requests/screen-0.html b/templates/requests/screen-0.html deleted file mode 100644 index 19f57d2e..00000000 --- a/templates/requests/screen-0.html +++ /dev/null @@ -1,12 +0,0 @@ -{% extends '../requests_new.html.to' %} - -{% block form %} -

New JEDI Request

- -

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 - -{% endblock %} diff --git a/templates/requests/screen-1.html b/templates/requests/screen-1.html index 88561030..22e9b100 100644 --- a/templates/requests/screen-1.html +++ b/templates/requests/screen-1.html @@ -1,4 +1,4 @@ -{% extends 'requests_new.html' %} +{% extends 'requests/_new.html' %} {% from "components/alert.html" import Alert %} {% from "components/text_input.html" import TextInput %} diff --git a/templates/requests/screen-2.html b/templates/requests/screen-2.html index 9a23777e..6d23c171 100644 --- a/templates/requests/screen-2.html +++ b/templates/requests/screen-2.html @@ -1,4 +1,4 @@ -{% extends 'requests_new.html' %} +{% extends 'requests/_new.html' %} {% from "components/alert.html" import Alert %} {% from "components/text_input.html" import TextInput %} diff --git a/templates/requests/screen-3.html b/templates/requests/screen-3.html index 79f4b3a0..cbceccae 100644 --- a/templates/requests/screen-3.html +++ b/templates/requests/screen-3.html @@ -1,4 +1,4 @@ -{% extends 'requests_new.html' %} +{% extends 'requests/_new.html' %} {% from "components/alert.html" import Alert %} {% from "components/text_input.html" import TextInput %} diff --git a/templates/requests/screen-4.html b/templates/requests/screen-4.html index c53b3a25..36fe1276 100644 --- a/templates/requests/screen-4.html +++ b/templates/requests/screen-4.html @@ -2,7 +2,7 @@ Response Required {%- endmacro %} -{% extends 'requests_new.html' %} +{% extends 'requests/_new.html' %} {% from "components/alert.html" import Alert %} {% from "components/text_input.html" import TextInput %} diff --git a/templates/requests/screen-5.html b/templates/requests/screen-5.html deleted file mode 100644 index 435b88cf..00000000 --- a/templates/requests/screen-5.html +++ /dev/null @@ -1,200 +0,0 @@ -{% extends '../requests_new.html.to' %} - -{% from "components/alert.html" import Alert %} - -{% block form %} - -{% if f.errors %} - {{ Alert('There were some errors', - message="

Please complete all the fields before submitting.

", - level='error' - ) }} -{% endif %} - - -

Financial Verification

-

In order to get you access to the JEDI Cloud, we will need you to enter the details below that will help us verify and account for your Task Order.

- -{{ f.task_order_number.label }} -{{ f.task_order_number(placeholder="Example: 1234567899C0001") }} -{% for e in f.task_order_number.errors %} -
- {{ e }} -
-{% endfor %} - -{{ f.uii_ids.label }} -{{ f.uii_ids(placeholder="Example: \nDI 0CVA5786950 \nUN1945326361234786950") }} -{% for e in f.uii_ids.errors %} -
- {{ e }} -
-{% endfor %} - -{{ f.pe_id.label }} -{{ f.pe_id(placeholder="Example: 0203752A") }} -{% for e in f.pe_id.errors %} -
- {{ e }} -
-{% endfor %} - -{{ f.treasury_code.label }} -{{ f.treasury_code(placeholder="Example: 1200") }} -{% for e in f.treasury_code.errors %} -
- {{ e }} -
-{% endfor %} - -{{ f.ba_code.label }} -{{ f.ba_code(placeholder="Example: 02") }} -{% for e in f.ba_code.errors %} -
- {{ e }} -
-{% endfor %} - - - -

Contracting Officer (KO) Information

- -{{ f.fname_co.label }} -{{ f.fname_co(placeholder="Contracting Officer first name") }} -{% for e in f.fname_co.errors %} -
- {{ e }} -
-{% endfor %} - -{{ f.lname_co.label }} -{{ f.lname_co(placeholder="Contracting Officer last name") }} -{% for e in f.lname_co.errors %} -
- {{ e }} -
-{% endfor %} - -{{ f.email_co.label }} -{{ f.email_co(placeholder="jane@mail.mil") }} -{% for e in f.email_co.errors %} -
- {{ e }} -
-{% endfor %} - -{{ f.office_co.label }} -{{ f.office_co(placeholder="Example: WHS") }} -{% for e in f.office_co.errors %} -
- {{ e }} -
-{% endfor %} - - - - -

Contracting Officer Representative (COR) Information

- -{{ f.fname_cor.label }} -{{ f.fname_cor(placeholder="Contracting Officer Representative first name") }} -{% for e in f.fname_cor.errors %} -
- {{ e }} -
-{% endfor %} - -{{ f.lname_cor.label }} -{{ f.lname_cor(placeholder="Contracting Officer Representative last name") }} -{% for e in f.lname_cor.errors %} -
- {{ e }} -
-{% endfor %} - -{{ f.email_cor.label }} -{{ f.email_cor(placeholder="jane@mail.mil") }} -{% for e in f.email_cor.errors %} -
- {{ e }} -
-{% endfor %} - -{{ f.office_cor.label }} -{{ f.office_cor(placeholder="Example: WHS") }} -{% for e in f.office_cor.errors %} -
- {{ e }} -
-{% endfor %} - -

-↓ FIELDS NEEDED FOR MANUAL ENTRY OF TASK ORDER INFORMATION (only necessary if EDA info not available) - - -{{ f.funding_type.label }} -{{ f.funding_type }} -{% for e in f.funding_type.errors %} -
- {{ e }} -
-{% endfor %} - -{{ f.funding_type_other.label }} -{{ f.funding_type_other(placeholder="") }} -{% for e in f.funding_type_other.errors %} -
- {{ e }} -
-{% endfor %} - -{{ f.clin_0001.label }} -{{ f.clin_0001(placeholder="50,000") }} -{% for e in f.clin_0001.errors %} -
- {{ e }} -
-{% endfor %} - -{{ f.clin_0003.label }} -{{ f.clin_0003(placeholder="13,000") }} -{% for e in f.clin_0003.errors %} -
- {{ e }} -
-{% endfor %} - -{{ f.clin_1001.label }} -{{ f.clin_1001(placeholder="30,000") }} -{% for e in f.clin_1001.errors %} -
- {{ e }} -
-{% endfor %} - -{{ f.clin_1003.label }} -{{ f.clin_1003(placeholder="7,000") }} -{% for e in f.clin_1003.errors %} -
- {{ e }} -
-{% endfor %} - -{{ f.clin_2001.label }} -{{ f.clin_2001(placeholder="30,000") }} -{% for e in f.clin_2001.errors %} -
- {{ e }} -
-{% endfor %} - -{{ f.clin_2003.label }} -{{ f.clin_2003(placeholder="7,000") }} -{% for e in f.clin_2003.errors %} -
- {{ e }} -
-{% endfor %} - - -{% endblock %} diff --git a/templates/base_workspace.html b/templates/workspaces/base.html similarity index 100% rename from templates/base_workspace.html rename to templates/workspaces/base.html diff --git a/templates/workspaces.html b/templates/workspaces/index.html similarity index 100% rename from templates/workspaces.html rename to templates/workspaces/index.html diff --git a/templates/member_edit.html b/templates/workspaces/members/edit.html similarity index 100% rename from templates/member_edit.html rename to templates/workspaces/members/edit.html diff --git a/templates/workspace_members.html b/templates/workspaces/members/index.html similarity index 98% rename from templates/workspace_members.html rename to templates/workspaces/members/index.html index 34761341..6c4f0b0f 100644 --- a/templates/workspace_members.html +++ b/templates/workspaces/members/index.html @@ -1,4 +1,4 @@ -{% extends "base_workspace.html" %} +{% extends "workspaces/base.html" %} {% from "components/empty_state.html" import EmptyState %} {% from "components/alert.html" import Alert %} diff --git a/templates/member_new.html b/templates/workspaces/members/new.html similarity index 100% rename from templates/member_new.html rename to templates/workspaces/members/new.html diff --git a/templates/workspaces/projects/edit.html b/templates/workspaces/projects/edit.html new file mode 100644 index 00000000..0a504091 --- /dev/null +++ b/templates/workspaces/projects/edit.html @@ -0,0 +1,17 @@ +{% extends "workspaces/base.html" %} + +{% from "components/alert.html" import Alert %} +{% from "components/icon.html" import Icon %} + +{% block workspace_content %} + +{{ Alert( + "UI Mock", + message="

Please note, this screen is a non-functional UI mockup.

", + level="warning" +) }} + +{% set modalName = "updateProjectConfirmation" %} +{% include "fragments/edit_project_form.html" %} + +{% endblock %} diff --git a/templates/workspace_projects.html b/templates/workspaces/projects/index.html similarity index 91% rename from templates/workspace_projects.html rename to templates/workspaces/projects/index.html index 81aa8a11..8dfaf373 100644 --- a/templates/workspace_projects.html +++ b/templates/workspaces/projects/index.html @@ -2,7 +2,7 @@ {% from "components/alert.html" import Alert %} {% from "components/empty_state.html" import EmptyState %} -{% extends "base_workspace.html" %} +{% extends "workspaces/base.html" %} {% block workspace_content %} @@ -25,7 +25,7 @@

{{ project.name }} ({{ project.environments|length }} environments)

- + {{ Icon('edit') }} edit diff --git a/templates/workspaces/projects/new.html b/templates/workspaces/projects/new.html new file mode 100644 index 00000000..765ff7d2 --- /dev/null +++ b/templates/workspaces/projects/new.html @@ -0,0 +1,17 @@ +{% extends "workspaces/base.html" %} + +{% block workspace_content %} + +{% set modalName = "newProjectConfirmation" %} +{% if request.args.get("newWorkspace") %} + {{ Alert('Workspace created!', + message="\ +

You are now ready to create projects and environments within the JEDI Cloud.

+ ", + level='success' + ) }} +{% endif %} + +{% include "fragments/edit_project_form.html" %} + +{% endblock %} diff --git a/templates/workspace_reports.html b/templates/workspaces/reports/index.html similarity index 99% rename from templates/workspace_reports.html rename to templates/workspaces/reports/index.html index 060f33e8..0bc1e503 100644 --- a/templates/workspace_reports.html +++ b/templates/workspaces/reports/index.html @@ -1,4 +1,4 @@ -{% extends "base_workspace.html" %} +{% extends "workspaces/base.html" %} {% from "components/alert.html" import Alert %} {% from "components/icon.html" import Icon %}