It is not possible to use task_data for an auto-complete field. It's too expensive an operation to provide that feature on the backend, and the data already fully resides on the front end anyway. Task-data can be used to populate enum fields if needed, so it can populate dropdowns, radios and checkboxes, just not auto-complete.

This commit is contained in:
Dan Funk 2020-07-14 11:38:48 -04:00
parent 463660f185
commit 9077ff3ebf
4 changed files with 30 additions and 52 deletions

View File

@ -144,7 +144,6 @@ class LookupFileModel(db.Model):
"""Gives us a quick way to tell what kind of lookup is set on a form field.
Connected to the file data model, so that if a new version of the same file is
created, we can update the listing."""
#fixme: What happens if they change the file associated with a lookup field?
__tablename__ = 'lookup_file'
id = db.Column(db.Integer, primary_key=True)
workflow_spec_id = db.Column(db.String)

View File

@ -4,7 +4,7 @@ from collections import OrderedDict
import pandas as pd
from pandas import ExcelFile, np
from sqlalchemy import func, desc
from sqlalchemy import desc
from sqlalchemy.sql.functions import GenericFunction
from crc import db
@ -119,40 +119,6 @@ class LookupService(object):
lookup_model = LookupService.build_lookup_table(data_model, value_column, label_column,
workflow_model.workflow_spec_id, field_id)
# Use the value of some other task data field to populate enum field options
elif field.has_property(Task.PROP_OPTIONS_DATA_NAME):
if not (field.has_property(Task.PROP_OPTIONS_DATA_VALUE_COLUMN) or
field.has_property(Task.PROP_OPTIONS_DATA_LABEL_COLUMN)):
raise ApiError.from_task("invalid_enum",
"For enumerations based on task data, you must include 3 properties: %s, "
"%s, and %s" % (Task.PROP_OPTIONS_DATA_NAME,
Task.PROP_OPTIONS_DATA_VALUE_COLUMN,
Task.PROP_OPTIONS_DATA_LABEL_COLUMN),
task=spiff_task)
prop = field.get_property(Task.PROP_OPTIONS_DATA_NAME)
if prop not in spiff_task.data:
raise ApiError.from_task("invalid_enum", "For enumerations based on task data, task data must have "
"a property called '%s'" % prop,
task=spiff_task)
# Get the enum options from the task data
data_model = spiff_task.data[prop]
value_column = field.get_property(Task.PROP_OPTIONS_DATA_VALUE_COLUMN)
label_column = field.get_property(Task.PROP_OPTIONS_DATA_LABEL_COLUMN)
lookup_model = LookupFileModel(workflow_spec_id=workflow_model.workflow_spec_id,
field_id=field_id,
is_ldap=False)
db.session.add(lookup_model)
items = data_model.items() if isinstance(data_model, dict) else data_model
for item in items:
lookup_data = LookupDataModel(lookup_file_model=lookup_model,
value=item[value_column],
label=item[label_column],
data=item)
db.session.add(lookup_data)
db.session.commit()
# Use the results of an LDAP request to populate enum field options
elif field.has_property(Task.PROP_LDAP_LOOKUP):
lookup_model = LookupFileModel(workflow_spec_id=workflow_model.workflow_spec_id,
@ -160,8 +126,8 @@ class LookupService(object):
is_ldap=True)
else:
raise ApiError("unknown_lookup_option",
"Lookup supports using spreadsheet, task data, or LDAP options, "
"and none of those was provided.")
"Lookup supports using spreadsheet or LDAP options, "
"and neither of those was provided.")
db.session.add(lookup_model)
db.session.commit()
return lookup_model
@ -247,3 +213,4 @@ class LookupService(object):
"data": user
})
return user_list

View File

@ -394,16 +394,39 @@ class WorkflowService(object):
# If this is an auto-complete field, do not populate options, a lookup will happen later.
if field.type == Task.FIELD_TYPE_AUTO_COMPLETE:
pass
elif field.has_property(Task.PROP_OPTIONS_FILE_NAME) or field.has_property(Task.PROP_OPTIONS_DATA_NAME):
elif field.has_property(Task.PROP_OPTIONS_FILE_NAME):
lookup_model = LookupService.get_lookup_model(spiff_task, field)
data = db.session.query(LookupDataModel).filter(LookupDataModel.lookup_file_model == lookup_model).all()
if not hasattr(field, 'options'):
field.options = []
for d in data:
field.options.append({"id": d.value, "name": d.label, "data": d.data})
elif field.has_property(Task.PROP_OPTIONS_DATA_NAME):
field.options = WorkflowService.get_options_from_task_data(spiff_task, field)
return field
@staticmethod
def get_options_from_task_data(spiff_task, field):
if not (field.has_property(Task.PROP_OPTIONS_DATA_VALUE_COLUMN) or
field.has_property(Task.PROP_OPTIONS_DATA_LABEL_COLUMN)):
raise ApiError.from_task("invalid_enum",
f"For enumerations based on task data, you must include 3 properties: "
f"{Task.PROP_OPTIONS_DATA_NAME}, {Task.PROP_OPTIONS_DATA_VALUE_COLUMN}, "
f"{Task.PROP_OPTIONS_DATA_LABEL_COLUMN}", task=spiff_task)
prop = field.get_property(Task.PROP_OPTIONS_DATA_NAME)
if prop not in spiff_task.data:
raise ApiError.from_task("invalid_enum", f"For enumerations based on task data, task data must have "
f"a property called {prop}", task=spiff_task)
# Get the enum options from the task data
data_model = spiff_task.data[prop]
value_column = field.get_property(Task.PROP_OPTIONS_DATA_VALUE_COLUMN)
label_column = field.get_property(Task.PROP_OPTIONS_DATA_LABEL_COLUMN)
items = data_model.items() if isinstance(data_model, dict) else data_model
options = []
for item in items:
options.append({"id": item[value_column], "name": item[label_column], "data": item})
return options
@staticmethod
def log_task_action(user_uid, workflow_model, spiff_task, action, version):
task = WorkflowService.spiff_task_to_api_task(spiff_task)

View File

@ -403,7 +403,7 @@ class TestTasksApi(BaseTest):
self.assert_options_populated(results, ['CUSTOMER_NUMBER', 'CUSTOMER_NAME', 'CUSTOMER_CLASS_MEANING'])
self.assertIsInstance(results[0]['data'], dict)
def test_lookup_endpoint_enum_in_task_data(self):
def test_enum_from_task_data(self):
self.load_example_data()
workflow = self.create_workflow('enum_options_from_task_data')
# get the first form in the two form workflow.
@ -428,17 +428,6 @@ class TestTasksApi(BaseTest):
self.assertEqual('Berthilda', options[1]['data']['first_name'])
self.assertEqual('Chesterfield', options[2]['data']['first_name'])
rv = self.app.get('/v1.0/workflow/%i/lookup/%s?value=%s' %
(workflow.id, field_id, option_id),
headers=self.logged_in_headers(),
content_type="application/json")
self.assert_success(rv)
results = json.loads(rv.get_data(as_text=True))
self.assertEqual(1, len(results))
self.assert_options_populated(results, ['first_name', 'last_name', 'age', 'likes_pie', 'num_lumps',
'secret_id', 'display_name'])
self.assertIsInstance(results[0]['data'], dict)
def test_lookup_endpoint_for_task_ldap_field_lookup(self):
self.load_example_data()
workflow = self.create_workflow('ldap_lookup')