Skip to content

Commit

Permalink
Bugfix multi input field (#73)
Browse files Browse the repository at this point in the history
* WIP - adding support for multi-input-field

* Adding children and schema to component definition

* Add options to page
  • Loading branch information
srh-sloan authored Oct 17, 2024
1 parent 65fc96b commit 6f509c1
Show file tree
Hide file tree
Showing 12 changed files with 1,185 additions and 8 deletions.
40 changes: 40 additions & 0 deletions app/db/migrations/versions/~2024_10_16_1347-da30746cec39_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""Add MultiInputField to ComponentType Enum and columns children and schema to Component. Add column options to Page
Revision ID: da30746cec39
Revises: ca61d3b746f6
Create Date: 2024-10-16 13:47:16.968837
"""
from alembic import op
import sqlalchemy as sa

from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = 'da30746cec39'
down_revision = 'ca61d3b746f6'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###

op.execute("ALTER TYPE componenttype ADD VALUE 'MULTI_INPUT_FIELD';")
with op.batch_alter_table('component', schema=None) as batch_op:
batch_op.add_column(sa.Column('children', postgresql.JSON(none_as_null=True, astext_type=sa.Text()), nullable=True))
batch_op.add_column(sa.Column('schema', postgresql.JSON(astext_type=sa.Text()), nullable=True))
with op.batch_alter_table('page', schema=None) as batch_op:
batch_op.add_column(sa.Column('options', postgresql.JSON(none_as_null=True, astext_type=sa.Text()), nullable=True))

# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('component', schema=None) as batch_op:
batch_op.drop_column('children')
batch_op.drop_column('schema')
with op.batch_alter_table('page', schema=None) as batch_op:
batch_op.drop_column('options')
# ### end Alembic commands ###
4 changes: 4 additions & 0 deletions app/db/models/application_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class ComponentType(Enum):
FILE_UPLOAD_FIELD = "FileUploadField"
MONTH_YEAR_FIELD = "MonthYearField"
TIME_FIELD = "TimeField"
MULTI_INPUT_FIELD="MultiInputField"


READ_ONLY_COMPONENTS = [
Expand Down Expand Up @@ -164,6 +165,7 @@ class Page(BaseModel):
)
source_template_id = Column(UUID(as_uuid=True), nullable=True)
controller = Column(String(), nullable=True)
options=Column(JSON(none_as_null=True))

def __repr__(self):
return f"Page(/{self.display_path} - {self.name_in_apply_json['en']}, Components: {self.components})"
Expand Down Expand Up @@ -220,10 +222,12 @@ class Component(BaseModel):
content = Column(String(), nullable=True)
hint_text = Column(String(), nullable=True)
options = Column(JSON(none_as_null=False))
schema = Column(JSON(none_as_null=False))
type = Column(ENUM(ComponentType))
template_name = Column(String(), nullable=True)
is_template = Column(Boolean, default=False, nullable=False)
audit_info = Column(JSON(none_as_null=True))
children = Column(JSON(none_as_null=True)) # TODO model this as a proper hierarchy
page_index = Column(Integer())
theme_index = Column(Integer())
conditions = Column(JSON(none_as_null=True))
Expand Down
7 changes: 6 additions & 1 deletion app/export_config/generate_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def build_component(component: Component) -> dict:
"type": component.type.value,
"title": component.title,
"hint": component.hint_text or "",
"schema": {},
"schema": component.schema or {},
"name": component.runner_component_name,
"metadata": {
# "fund_builder_id": str(component.component_id) TODO why do we need this?
Expand All @@ -108,6 +108,9 @@ def build_component(component: Component) -> dict:
built_component["metadata"].update({"fund_builder_list_id": str(component.list_id)})
built_component.update({"values": {"type": "listRef"}})

if component.type is ComponentType.MULTI_INPUT_FIELD:
built_component.update({"children":component.children})

return built_component


Expand All @@ -124,6 +127,8 @@ def build_page(page: Page = None) -> dict:
"title": page.name_in_apply_json["en"],
}
)
if page.options:
built_page.update({"options": page.options})
# Having a 'null' controller element breaks the form-json, needs to not be there if blank
if page.controller:
built_page["controller"] = page.controller
Expand Down
6 changes: 5 additions & 1 deletion app/export_config/generate_fund_round_form_jsons.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"properties": {
"path": {"type": "string"},
"title": {"type": "string"},
"options":{"type":"object"},
"components": {
"type": "array",
"items": {
Expand All @@ -34,11 +35,14 @@
"title": {"type": ["string", "null"]},
"content": {"type": ["string", "null"]},
"hint": {"type": "string"},
"schema": {"type": "object"},
"schema": {
"type": "object",
},
"name": {"type": "string"},
"metadata": {
"type": "object",
},
"children": {"type": "array"}
},
},
},
Expand Down
3 changes: 3 additions & 0 deletions app/import_config/load_form_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ def insert_component_as_template(component, page_id, page_index, lizts):
# theme_index=component.get('theme_index', None), TODO: add theme_index to json
runner_component_name=component.get("name", None),
list_id=list_id,
children=component.get("children", None),
schema=component.get("schema", None)
)
try:
db.session.add(new_component)
Expand All @@ -147,6 +149,7 @@ def insert_page_as_template(page, form_id):
controller=page.get("controller", None),
is_template=True,
template_name=page.get("title", None),
options = page.get("options", None),
)
try:
db.session.add(new_page)
Expand Down
25 changes: 23 additions & 2 deletions tests/test_config_import.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import json
import os
from pathlib import Path

import pytest

from app.db.models import Component
from app.db.models import Form
from app.db.models import Page
from app.db.models.application_config import ComponentType
from app.import_config.load_form_json import load_form_jsons
from app.import_config.load_form_json import load_json_from_file

Expand Down Expand Up @@ -49,8 +51,7 @@ def test_generate_config_for_round_valid_input(seed_dynamic_data, _db, filename)
def test_generate_config_for_round_valid_input_file(seed_dynamic_data, _db):
filename = "test-import-form.json"
template_name = "test-template"
script_dir = os.path.dirname(__file__)
file_path = os.path.join(script_dir, filename)
file_path = Path("tests") / "test_data" / filename
with open(file_path, "r") as json_file:
form = json.load(json_file)
form["filename"] = filename
Expand All @@ -70,3 +71,23 @@ def test_generate_config_for_round_valid_input_file(seed_dynamic_data, _db):
_db.session.query(Component).filter(Component.page_id == page.page_id).count() for page in pages
)
assert total_components_count == expected_component_count_for_form


def test_import_multi_input_field(seed_dynamic_data, _db):
with open(Path("tests") / "test_data" / "multi_input.json", "r") as json_file:
form = json.load(json_file)
form["filename"] = "test_mult_input"

load_json_from_file(form, template_name="test_input_multi_input")
forms = _db.session.query(Form).filter(Form.template_name == "test_input_multi_input")
assert forms.count() == 1
pages = _db.session.query(Page).filter(Page.form_id == forms.first().form_id)
assert pages.count() == 3
page_with_multi_input = next(p for p in pages if p.display_path=='capital-costs-for-your-project')
assert page_with_multi_input
assert page_with_multi_input.options
multi_input_component = next(c for c in page_with_multi_input.components if c.title=='Capital costs')
assert multi_input_component
assert multi_input_component.type == ComponentType.MULTI_INPUT_FIELD
assert len(multi_input_component.children) == 4

Loading

0 comments on commit 6f509c1

Please sign in to comment.