From d9e66e04c2ba2e2da574085039663daef56313b0 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Wed, 22 Aug 2018 16:58:29 -0400 Subject: [PATCH 01/12] Send valid form data --- js/components/forms/new_project.js | 6 ++++-- templates/workspace_project_new.html | 7 ++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/js/components/forms/new_project.js b/js/components/forms/new_project.js index cbea6161..1565cadc 100644 --- a/js/components/forms/new_project.js +++ b/js/components/forms/new_project.js @@ -1,5 +1,7 @@ import textinput from '../text_input' +const createEnvironment = (name) => ({ name }) + export default { name: 'new-project', @@ -18,7 +20,7 @@ export default { const { name, description, - environments = [''] + environments = [ createEnvironment() ] } = this.initialData return { @@ -34,7 +36,7 @@ export default { methods: { addEnvironment: function (event) { - this.environments.push('') + this.environments.push(createEnvironment("")) }, removeEnvironment: function (index) { diff --git a/templates/workspace_project_new.html b/templates/workspace_project_new.html index 85cdf673..877729fb 100644 --- a/templates/workspace_project_new.html +++ b/templates/workspace_project_new.html @@ -34,13 +34,14 @@ + {{ form.environment_names.errors }} From fc07ef523006d99ebbbf7db5fb03449e0a13d436 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Wed, 22 Aug 2018 16:59:39 -0400 Subject: [PATCH 02/12] Validate and filter environment_names form input --- atst/forms/new_project.py | 21 +++++++++++++++++---- atst/forms/validators.py | 11 +++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/atst/forms/new_project.py b/atst/forms/new_project.py index 1552a1ab..9af3ac0c 100644 --- a/atst/forms/new_project.py +++ b/atst/forms/new_project.py @@ -1,9 +1,22 @@ from flask_wtf import Form -from wtforms.fields import StringField, TextAreaField +from wtforms.fields import StringField, TextAreaField, FieldList +from wtforms.validators import Required +from atst.forms.validators import ListItemRequired class NewProjectForm(Form): - name = StringField(label="Project Name") - description = TextAreaField(label="Description") - environment_name = StringField(label="Environment Name") + EMPTY_ENVIRONMENT_NAMES = ["", None] + + name = StringField(label="Project Name", validators=[Required()]) + description = TextAreaField(label="Description", validators=[Required()]) + environment_names = FieldList( + StringField(label="Environment Name"), + validators=[ListItemRequired(message="Provide at least one environment name.")], + ) + + @property + def data(self): + _data = super(Form, self).data + _data["environment_names"] = [n for n in _data["environment_names"] if n not in self.EMPTY_ENVIRONMENT_NAMES] + return _data diff --git a/atst/forms/validators.py b/atst/forms/validators.py index 241a5401..85173383 100644 --- a/atst/forms/validators.py +++ b/atst/forms/validators.py @@ -51,3 +51,14 @@ def Alphabet(message="Please enter only letters."): raise ValidationError(message) return _alphabet + + +def ListItemRequired(message="Please provide at least one.", empty_values=("", None)): + def _list_item_required(form, field): + non_empty_values = [v for v in field.data if v not in empty_values] + if len(non_empty_values) == 0: + raise ValidationError(message) + + return _list_item_required + + From 8ac271e83e28a30f874c9f8abdda67a37438c5eb Mon Sep 17 00:00:00 2001 From: richard-dds Date: Wed, 22 Aug 2018 17:00:05 -0400 Subject: [PATCH 03/12] Create environments while creating project --- atst/domain/environments.py | 6 ++++++ atst/domain/projects.py | 4 +++- atst/routes/workspaces.py | 12 +++++++++--- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/atst/domain/environments.py b/atst/domain/environments.py index 90755052..be007740 100644 --- a/atst/domain/environments.py +++ b/atst/domain/environments.py @@ -10,3 +10,9 @@ class Environments(object): db.session.commit() return environment + @classmethod + def create_many(cls, project, names): + for name in names: + environment = Environment(project=project, name=name) + db.session.add(environment) + db.session.commit() diff --git a/atst/domain/projects.py b/atst/domain/projects.py index 16e0fc4c..d3b2848a 100644 --- a/atst/domain/projects.py +++ b/atst/domain/projects.py @@ -1,11 +1,13 @@ from atst.database import db from atst.models.project import Project +from atst.domain.environments import Environments class Projects(object): @classmethod - def create(cls, workspace, name, description): + def create(cls, workspace, name, description, environment_names): project = Project(workspace=workspace, name=name, description=description) + Environments.create_many(project, environment_names) db.session.add(project) db.session.commit() diff --git a/atst/routes/workspaces.py b/atst/routes/workspaces.py index 6b25a04d..bfb5a428 100644 --- a/atst/routes/workspaces.py +++ b/atst/routes/workspaces.py @@ -67,10 +67,16 @@ def update_project(workspace_id): if form.validate(): project_data = form.data - project = Projects.create( - workspace, project_data["name"], project_data["description"] + Projects.create( + workspace, + project_data["name"], + project_data["description"], + project_data["environment_names"], ) - Environments.create(project, project_data["environment_name"]) return redirect( url_for("workspaces.workspace_projects", workspace_id=workspace.id) ) + else: + return render_template( + "workspace_project_new.html", workspace=workspace, form=form + ) From 814ec5a513cf28d08677d091a5543d7ae986b1b1 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Wed, 22 Aug 2018 17:05:53 -0400 Subject: [PATCH 04/12] Add test for Projects.create --- tests/domain/test_projects.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tests/domain/test_projects.py diff --git a/tests/domain/test_projects.py b/tests/domain/test_projects.py new file mode 100644 index 00000000..e2b8a52b --- /dev/null +++ b/tests/domain/test_projects.py @@ -0,0 +1,12 @@ +from atst.domain.projects import Projects +from tests.factories import WorkspaceFactory + + +def test_create_project_with_multiple_environments(): + workspace = WorkspaceFactory.create() + project = Projects.create(workspace, "My Test Project", "Test", ["dev", "prod"]) + + assert project.workspace == workspace + assert project.name == "My Test Project" + assert project.description == "Test" + assert [e.name for e in project.environments] == ["dev", "prod"] From dd80b9c5584d401f25cc0591291e7ef7e27b6ebd Mon Sep 17 00:00:00 2001 From: richard-dds Date: Wed, 22 Aug 2018 17:07:08 -0400 Subject: [PATCH 05/12] Formatting --- atst/forms/new_project.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/atst/forms/new_project.py b/atst/forms/new_project.py index 9af3ac0c..65685e70 100644 --- a/atst/forms/new_project.py +++ b/atst/forms/new_project.py @@ -18,5 +18,9 @@ class NewProjectForm(Form): @property def data(self): _data = super(Form, self).data - _data["environment_names"] = [n for n in _data["environment_names"] if n not in self.EMPTY_ENVIRONMENT_NAMES] + _data["environment_names"] = [ + n + for n in _data["environment_names"] + if n not in self.EMPTY_ENVIRONMENT_NAMES + ] return _data From 2daad4d057b590fafb42701c1ec38b7ceb68e05e Mon Sep 17 00:00:00 2001 From: richard-dds Date: Thu, 23 Aug 2018 10:33:40 -0400 Subject: [PATCH 06/12] Styling new project form --- templates/workspace_project_new.html | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/templates/workspace_project_new.html b/templates/workspace_project_new.html index 877729fb..a46c5191 100644 --- a/templates/workspace_project_new.html +++ b/templates/workspace_project_new.html @@ -34,14 +34,22 @@
    -
  • - {{ form.environment_names.label }} - - {{ Icon('x') }} Remove +
  • +
    +
    +
- {{ form.environment_names.errors }} + {% for error in form.environment_names.errors %} + {{ error }} + {% endfor %} + From 5210b9e17a339454a24fe5f8c8dc2225e0ad07f4 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Thu, 23 Aug 2018 10:33:53 -0400 Subject: [PATCH 07/12] Correctly format incoming environment names --- js/components/forms/new_project.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/js/components/forms/new_project.js b/js/components/forms/new_project.js index 1565cadc..ba4e13f5 100644 --- a/js/components/forms/new_project.js +++ b/js/components/forms/new_project.js @@ -18,14 +18,16 @@ export default { data: function () { const { - name, - description, - environments = [ createEnvironment() ] + environment_names, } = this.initialData + const environments = ( + environment_names.length > 0 + ? environment_names + : [""] + ).map(createEnvironment) + return { - name, - description, environments, } }, From e68ddfb06d8a107e06d9cd4ae3b5c60e89040449 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Thu, 23 Aug 2018 11:43:25 -0400 Subject: [PATCH 08/12] Display alert for environment_names errors --- templates/workspace_project_new.html | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/templates/workspace_project_new.html b/templates/workspace_project_new.html index a46c5191..6a09c856 100644 --- a/templates/workspace_project_new.html +++ b/templates/workspace_project_new.html @@ -1,6 +1,7 @@ {% from "components/icon.html" import Icon %} {% from "components/text_input.html" import TextInput %} {% from "components/tooltip.html" import Tooltip %} +{% from "components/alert.html" import Alert %} {% extends "base_workspace.html" %} @@ -24,6 +25,10 @@ + {% if form.environment_names.errors %} + {{ Alert("Missing Environments", message="Provide at least one environment name.", level="error") }} + {% endif %} +

Project Environments

@@ -46,10 +51,6 @@ - {% for error in form.environment_names.errors %} - {{ error }} - {% endfor %} - From 7a8b0a2562779745b0497fe6fb05f85fa0dc6305 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Thu, 23 Aug 2018 11:50:21 -0400 Subject: [PATCH 09/12] Don't show trash icon on first environment name input --- templates/workspace_project_new.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/workspace_project_new.html b/templates/workspace_project_new.html index 6a09c856..fb24b2b1 100644 --- a/templates/workspace_project_new.html +++ b/templates/workspace_project_new.html @@ -44,8 +44,8 @@
- From 8d6c64f990d65da732c857bd9083ed6fd66246e4 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Thu, 23 Aug 2018 12:03:46 -0400 Subject: [PATCH 10/12] Remove unused import --- atst/routes/workspaces.py | 1 - 1 file changed, 1 deletion(-) diff --git a/atst/routes/workspaces.py b/atst/routes/workspaces.py index bfb5a428..aab9af39 100644 --- a/atst/routes/workspaces.py +++ b/atst/routes/workspaces.py @@ -9,7 +9,6 @@ from flask import ( from atst.domain.workspaces import Workspaces from atst.domain.projects import Projects -from atst.domain.environments import Environments from atst.forms.new_project import NewProjectForm bp = Blueprint("workspaces", __name__) From f2d2f1ee022a61b5280a8d05c5cdf2124c935e39 Mon Sep 17 00:00:00 2001 From: luis cielak Date: Thu, 23 Aug 2018 14:32:11 -0400 Subject: [PATCH 11/12] Fixes to tooltip margins and input text label/bolding issue --- styles/elements/_block_lists.scss | 3 ++- styles/sections/_project_edit.scss | 2 +- templates/workspace_project_new.html | 12 ++++++------ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/styles/elements/_block_lists.scss b/styles/elements/_block_lists.scss index ade36741..f0549853 100644 --- a/styles/elements/_block_lists.scss +++ b/styles/elements/_block_lists.scss @@ -17,7 +17,8 @@ justify-content: space-between; .icon-tooltip { - padding: 0.25rem 0.5rem; + margin: -$gap; + } } diff --git a/styles/sections/_project_edit.scss b/styles/sections/_project_edit.scss index 2222fd26..ef1bc39a 100644 --- a/styles/sections/_project_edit.scss +++ b/styles/sections/_project_edit.scss @@ -13,7 +13,7 @@ @include icon-link-vertical; @include icon-link-color($color-red, $color-red-lightest); - margin-bottom: -$gap; + margin-bottom: 0; margin-right: -$gap; } } diff --git a/templates/workspace_project_new.html b/templates/workspace_project_new.html index fb24b2b1..874f93d3 100644 --- a/templates/workspace_project_new.html +++ b/templates/workspace_project_new.html @@ -41,13 +41,13 @@
  • -
    - +
From 7a9405ba2f0de15bb04f20493c4423dfc4cfa78c Mon Sep 17 00:00:00 2001 From: richard-dds Date: Thu, 23 Aug 2018 14:31:54 -0400 Subject: [PATCH 12/12] Sort environment names so our assert is deterministic --- tests/domain/test_projects.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/domain/test_projects.py b/tests/domain/test_projects.py index e2b8a52b..8845c04a 100644 --- a/tests/domain/test_projects.py +++ b/tests/domain/test_projects.py @@ -9,4 +9,4 @@ def test_create_project_with_multiple_environments(): assert project.workspace == workspace assert project.name == "My Test Project" assert project.description == "Test" - assert [e.name for e in project.environments] == ["dev", "prod"] + assert sorted(e.name for e in project.environments) == ["dev", "prod"]