From 84ce24243fbed32e10395fa9fabcade28d569242 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 21 Oct 2021 13:57:49 -0400 Subject: [PATCH] add an enum_label script that will return the label given a value selection. --- crc/scripts/enum_label.py | 85 ++++++++++++ crc/services/lookup_service.py | 2 +- crc/services/workflow_processor.py | 17 ++- .../enum_options_all/enum_options_all.bpmn | 131 ++++++++++++++++++ tests/data/enum_options_all/my_list.xlsx | Bin 0 -> 5008 bytes tests/scripts/test_get_enum_label.py | 56 ++++++++ 6 files changed, 286 insertions(+), 5 deletions(-) create mode 100644 crc/scripts/enum_label.py create mode 100644 tests/data/enum_options_all/enum_options_all.bpmn create mode 100644 tests/data/enum_options_all/my_list.xlsx create mode 100644 tests/scripts/test_get_enum_label.py diff --git a/crc/scripts/enum_label.py b/crc/scripts/enum_label.py new file mode 100644 index 00000000..59bdd890 --- /dev/null +++ b/crc/scripts/enum_label.py @@ -0,0 +1,85 @@ +from crc import db +from crc.api.common import ApiError +from crc.models.api_models import Task +from crc.models.workflow import WorkflowModel +from crc.scripts.script import Script +from crc.services.lookup_service import LookupService +from crc.services.workflow_processor import WorkflowProcessor + + +class EnumLabel(Script): + + UNKNOWN = "unknown" + + def get_description(self): + return """In a form, when doing a select list, multi-select, autocomplete, etc... you are left with a single + value. You may want to know the label that was displayed to the user as well. This will return the label, given + enough information to do so, which requires the name of the user task, the name of the form field, and the value + of the selected item. + +Example: +pet_label = enum_label('task_pet_form', 'pet', '1') // might return 'Dog' which has the value of 1 +""" + + def do_task_validate_only(self, task, study_id, workflow_id, *args, **kwargs): + return self.do_task(task, study_id, workflow_id, *args, **kwargs) + + def do_task(self, task, study_id, workflow_id, *args, **kwargs): + + self.validate_arguments(**kwargs) + + task_name = kwargs['task_name'] + field_name = kwargs['field'] + value = kwargs['value'] + + # get the field information for the provided task_name (NOT the current task) + workflow_model = db.session.query(WorkflowModel).filter(WorkflowModel.id == workflow_id).first() + processor = WorkflowProcessor(workflow_model) + spec, field = processor.find_spec_and_field(task_name, field_name) + print(spec) + print(field) + + if field.type == Task.FIELD_TYPE_AUTO_COMPLETE: + return self.autocomplete_label(workflow_model, task_name, field, value) + elif field.type == Task.FIELD_TYPE_ENUM and hasattr(field, 'options'): + return self.enum_with_options_label(field, value) + elif field.has_property(Task.FIELD_PROP_DATA_NAME): + return self.enum_from_task_data_label(task, field, value) + + def autocomplete_label(self, workflow_model, task_name, field, value): + label_column = field.get_property(Task.FIELD_PROP_LABEL_COLUMN) + result = LookupService().lookup(workflow_model, task_name, field.id, '', value=value, limit=1) + if len(result) > 0: + return result[0][label_column] + else: + return self.UNKNOWN + + def enum_with_options_label(self, field, value): + for option in field.options: + if option.id == value: + return option.name + return self.UNKNOWN + + def enum_from_task_data_label(self, task, field, value): + data_name = field.get_property(Task.FIELD_PROP_DATA_NAME) + value_column = field.get_property(Task.FIELD_PROP_VALUE_COLUMN) + label_column = field.get_property(Task.FIELD_PROP_LABEL_COLUMN) + if data_name in task.data: + for d in task.data[data_name]: + if d[value_column] == value: + return d[label_column] + return self.UNKNOWN + + def validate_arguments(self, **kwargs): + if len(kwargs) != 3: + raise ApiError(code="invalid_argument", + message="enum_label requires three arguments: Task id, Field id, and the selected value.") + if not 'task_name' in kwargs: + raise ApiError(code="invalid_argument", + message="you must specify the 'task_name', that is the name of the task with a form and field") + if not 'field' in kwargs: + raise ApiError(code="invalid_argument", + message="you must specify the 'field', that is the name of the field with an enum.") + if not 'value' in kwargs: + raise ApiError(code="invalid_argument", + message="you must specify the 'value', that is the value of the enum you wish to get a label for.") diff --git a/crc/services/lookup_service.py b/crc/services/lookup_service.py index 0c8825cf..b9eaeba7 100644 --- a/crc/services/lookup_service.py +++ b/crc/services/lookup_service.py @@ -85,7 +85,7 @@ class LookupService(object): @staticmethod def lookup(workflow, task_spec_id, field_id, query, value=None, limit=10): - + # Returns a list of dictionaries lookup_model = LookupService.__get_lookup_model(workflow, task_spec_id, field_id) if lookup_model.is_ldap: diff --git a/crc/services/workflow_processor.py b/crc/services/workflow_processor.py index 40717af3..ed3d1d3a 100644 --- a/crc/services/workflow_processor.py +++ b/crc/services/workflow_processor.py @@ -481,12 +481,21 @@ class WorkflowProcessor(object): for task in self.bpmn_workflow.get_ready_user_tasks(): if task.workflow not in workflows: workflows.append(task.workflow) - + spec_found = False for workflow in workflows: for spec in workflow.spec.task_specs.values(): - if spec.name == spec_name and hasattr(spec, "form"): + if spec.name == spec_name: + spec_found = True + if not hasattr(spec, "form"): + raise ApiError("invalid_spec", + "The spec name you provided does not contain a form.") + for field in spec.form.fields: if field.id == field_id: return spec, field - raise ApiError("invalid_field", - "Unable to find a task in the workflow with a lookup field called: %s" % field_id) + + raise ApiError("invalid_field", + f"The task '{spec_name}' has no field named '{field_id}'") + + raise ApiError("invalid_spec", + f"Unable to find a task in the workflow called '{spec_name}'") diff --git a/tests/data/enum_options_all/enum_options_all.bpmn b/tests/data/enum_options_all/enum_options_all.bpmn new file mode 100644 index 00000000..4b6d1428 --- /dev/null +++ b/tests/data/enum_options_all/enum_options_all.bpmn @@ -0,0 +1,131 @@ + + + + + Flow_173zivg + + + + + # This is what was entered + Flow_0f9fac8 + + + + Flow_173zivg + Flow_1e3q669 + dogs = [ + {'label':'Ham','value':'ham'}, + {'label':'Ginger','value':'ginger'}, + {'label':'Etta','value':'etta'}, + {'label':'Simo','value':'simo'}, +] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Flow_1e3q669 + Flow_0f9fac8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/data/enum_options_all/my_list.xlsx b/tests/data/enum_options_all/my_list.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..99765dccff41fd90ea865cb156dbf206fc67fe7b GIT binary patch literal 5008 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