diff --git a/app/plugins/CoreEnroller/src/Controller/AttributeCollectorsController.php b/app/plugins/CoreEnroller/src/Controller/AttributeCollectorsController.php index 27faa2749..7665edb2d 100644 --- a/app/plugins/CoreEnroller/src/Controller/AttributeCollectorsController.php +++ b/app/plugins/CoreEnroller/src/Controller/AttributeCollectorsController.php @@ -30,9 +30,9 @@ namespace CoreEnroller\Controller; use App\Controller\StandardEnrollerController; -use App\Lib\Enum\PetitionStatusEnum; use Cake\Event\EventInterface; use Cake\Http\Response; +use Cake\ORM\TableRegistry; class AttributeCollectorsController extends StandardEnrollerController { public $paginate = [ @@ -125,12 +125,19 @@ public function dispatch(string $id) { /** * Display information about this Step. * - * @since COmanage Registry v5.0.0 + * @since COmanage Registry v5.1.0 * @param string $id Attribute Collector ID */ - public function display(string $id) { - debug("display something for this petition"); - debug($this->getPetition()); + public function display(string $id): void { + $petition = $this->getPetition(); + + $this->set('vv_petition_attributes', + $this->AttributeCollectors + ->EnrollmentAttributes + ->PetitionAttributes + ->find() + ->where(['petition_id' => $petition->id]) + ->all()); } } diff --git a/app/plugins/CoreEnroller/src/Model/Table/AttributeCollectorsTable.php b/app/plugins/CoreEnroller/src/Model/Table/AttributeCollectorsTable.php index 18e3c22e9..bd5b1d27a 100644 --- a/app/plugins/CoreEnroller/src/Model/Table/AttributeCollectorsTable.php +++ b/app/plugins/CoreEnroller/src/Model/Table/AttributeCollectorsTable.php @@ -166,15 +166,33 @@ public function upsert(int $id, int $petitionId, array $attributes) { foreach($attributes as $enrollmentAttributeLabel => $value) { // Remove field- prefix from the form field name - $enrollmentAttributeId = (int)substr($enrollmentAttributeLabel, 6); + $fieldToParts = explode('-', $enrollmentAttributeLabel); + // MVAs have multiple columns. For example a name has: + // given, surname, prefix, ... + $columnName = null; + if (count($fieldToParts) > 2) { + // There is a type ID in the middle + $columnName = $fieldToParts[1]; + } + // The enrollment Attribute ID is the last part + $enrollmentAttributeId = (int)array_pop($fieldToParts); + + // The people picker will send a complex string and not just the id. We need to extract it ourselves. + $re = '/^.*\(ID: (\d+)\)$/m'; + preg_match_all($re, $value, $matches, PREG_SET_ORDER, 0); + if(!empty($matches)) { + $value = $matches[0][1]; + } $newAttribute = [ 'petition_id' => $petitionId, 'enrollment_attribute_id' => $enrollmentAttributeId, - 'value' => $value + 'value' => $value, + // This is the column name for the attributes that consist of multiple fields, like the name or the address + 'column_name' => $columnName, ]; - if(array_key_exists($enrollmentAttributeId, $currentAttributes)) { + if(\array_key_exists($enrollmentAttributeId, $currentAttributes)) { // This is an update of an existing attribute $newAttribute['id'] = $currentAttributes[$enrollmentAttributeId]; diff --git a/app/plugins/CoreEnroller/src/Model/Table/PetitionAttributesTable.php b/app/plugins/CoreEnroller/src/Model/Table/PetitionAttributesTable.php index 161d873eb..d26329d5f 100644 --- a/app/plugins/CoreEnroller/src/Model/Table/PetitionAttributesTable.php +++ b/app/plugins/CoreEnroller/src/Model/Table/PetitionAttributesTable.php @@ -103,6 +103,7 @@ public function validationDefault(Validator $validator): Validator { $validator->notEmptyString('enrollment_attribute_id'); $this->registerStringValidation($validator, $schema, 'value', false); + $this->registerStringValidation($validator, $schema, 'column', false); return $validator; } diff --git a/app/plugins/CoreEnroller/src/config/plugin.json b/app/plugins/CoreEnroller/src/config/plugin.json index dbb666b8a..bb58ddb56 100644 --- a/app/plugins/CoreEnroller/src/config/plugin.json +++ b/app/plugins/CoreEnroller/src/config/plugin.json @@ -111,7 +111,8 @@ "id": {}, "petition_id": {}, "enrollment_attribute_id": { "type": "integer", "foreignkey": { "table": "enrollment_attributes", "column": "id" } }, - "value": { "type": "string", "size": 160 } + "value": { "type": "string", "size": 160 }, + "column_name": { "notnull": false, "type": "string", "size": 64 } }, "indexes": { "petition_attributes_i1": { "columns": [ "petition_id" ] }, diff --git a/app/plugins/CoreEnroller/templates/AttributeCollectors/display.php b/app/plugins/CoreEnroller/templates/AttributeCollectors/display.php new file mode 100644 index 000000000..f25efb457 --- /dev/null +++ b/app/plugins/CoreEnroller/templates/AttributeCollectors/display.php @@ -0,0 +1,8 @@ +toArray(); +?> + diff --git a/app/plugins/CoreEnroller/templates/EnrollmentAttributes/fields.inc b/app/plugins/CoreEnroller/templates/EnrollmentAttributes/fields.inc index 0ea015f21..09a3a971d 100644 --- a/app/plugins/CoreEnroller/templates/EnrollmentAttributes/fields.inc +++ b/app/plugins/CoreEnroller/templates/EnrollmentAttributes/fields.inc @@ -32,8 +32,7 @@ use \Cake\Utility\Inflector; $attribute_type = null; if($vv_action == 'add') { $attribute_type = $this->request->getQuery('attribute_type'); -} else if($vv_action == 'edit' && !empty($vv_obj) -) { +} else if($vv_action == 'edit' && !empty($vv_obj)) { $attribute_type = $vv_obj->attribute; } diff --git a/app/plugins/CoreEnroller/templates/element/field.php b/app/plugins/CoreEnroller/templates/element/field.php index b5cd48d5a..80a3b8cd4 100644 --- a/app/plugins/CoreEnroller/templates/element/field.php +++ b/app/plugins/CoreEnroller/templates/element/field.php @@ -119,5 +119,5 @@ 'formArguments' => $formArguments ]), // Default use case - default => $this->element('form/listItem', ['arguments' => $formArguments]) + default => $this->Field->getElementsForDisabledInput('form/listItem', $formArguments) }; diff --git a/app/plugins/CoreEnroller/templates/element/mveas/fieldset-field.php b/app/plugins/CoreEnroller/templates/element/mveas/fieldset-field.php index 58c89298c..4a1624761 100644 --- a/app/plugins/CoreEnroller/templates/element/mveas/fieldset-field.php +++ b/app/plugins/CoreEnroller/templates/element/mveas/fieldset-field.php @@ -38,12 +38,39 @@ $isRequiredFromValidationRule = false; $supportedAttributes = $this->Petition->getSupportedEnrollmentAttribute($attr->attribute); +// Field Options array +$options = []; + if(isset($supportedAttributes['mveaModel'])) { $supportedAttributes = $this->Petition->getSupportedEnrollmentAttribute($attr->attribute); $modelTable = $this->Petition->getTable($supportedAttributes['mveaModel']); $isRequiredFromValidationRule = !$modelTable->getValidator()->field($field)->isEmptyAllowed(); } +// Do we have a default value configured? +// Either a value or an Environmental Variable, +// Each default value is mutually exclusive to the rest. We do not have to worry about a conflict. +$options['default'] = match(true) { + isset($attr->default_value) => $attr->default_value, + isset($attr->default_value_env_name) + && getenv($attr->default_value_env_name) !== false => getenv($attr->default_value_env_name), + isset($attr->default_value_datetime) => $attr->default_value_datetime, + default => '' +}; + +// If we are re-rendering the Petition, override the default value with whatever +// was previously saved +if(!empty($vv_petition_attributes)) { + $curEntity = $vv_petition_attributes->firstMatch([ + 'enrollment_attribute_id' => $attr->id, + 'column_name' => $field + ]); + + if(!empty($curEntity->value)) { + $options['default'] = $curEntity->value; + } +} + // Construct the field arguments $formArguments = [ // We prefix the attribute ID with a string because Cake seems to sometimes have @@ -53,6 +80,9 @@ 'fieldType' => $modelTable->getSchema()->getColumn($field)['type'], 'fieldNameAlias' => $attr->attribute // the field name to its enrollment attribute field name ]; + +// Set the final fieldOptions +$formArguments['fieldOptions'] = $options; ?>
"> diff --git a/app/src/Model/Table/PetitionsTable.php b/app/src/Model/Table/PetitionsTable.php index fd760387e..e999b7d80 100644 --- a/app/src/Model/Table/PetitionsTable.php +++ b/app/src/Model/Table/PetitionsTable.php @@ -90,6 +90,9 @@ public function initialize(array $config): void { $this->hasMany('PetitionStepResults') ->setDependent(true) ->setCascadeCallbacks(true); + $this->hasMany('PetitionAttributes') + ->setDependent(true) + ->setCascadeCallbacks(true); $this->hasOne('Verifications') ->setDependent(true) @@ -116,7 +119,8 @@ public function initialize(array $config): void { 'EnrolleePeople' => ['PrimaryName' => ['foreignKey' => 'person_id']], 'PetitionerPeople' => ['PrimaryName' => ['foreignKey' => 'person_id']], 'PetitionHistoryRecords', - 'PetitionStepResults' + 'PetitionStepResults', + 'PetitionAttributes', ]); $this->setAutoViewVars([ diff --git a/app/src/View/Helper/FieldHelper.php b/app/src/View/Helper/FieldHelper.php index 4a221150c..34ca57ce3 100644 --- a/app/src/View/Helper/FieldHelper.php +++ b/app/src/View/Helper/FieldHelper.php @@ -304,7 +304,7 @@ public function dateField(string $fieldName, isset($fieldArgs['default']) && is_string($fieldArgs['default']) => FrozenTime::parse($fieldArgs['default']), // Petition View/ Value saved a FronzenTime isset($fieldArgs['default']) - && is_a($fieldArgs['default'], 'Cake\I18n\FrozenTime') => $fieldArgs['default'], + && is_a($fieldArgs['default'], 'Cake\I18n\FrozenTime') => $fieldArgs['default'], // Table record/ Retrieve it from the Entity object default => $this->getEntity()?->$fieldName, }; diff --git a/app/src/View/Helper/PetitionHelper.php b/app/src/View/Helper/PetitionHelper.php index 0f1ddec59..a23edf2e0 100644 --- a/app/src/View/Helper/PetitionHelper.php +++ b/app/src/View/Helper/PetitionHelper.php @@ -35,6 +35,7 @@ use Cake\Utility\Inflector; use Cake\View\Helper; use CoreEnroller\Model\Table\EnrollmentAttributesTable; +use DOMDocument; class PetitionHelper extends Helper { diff --git a/app/templates/Petitions/fields.inc b/app/templates/Petitions/fields.inc index 1665c1682..a0a0cb007 100644 --- a/app/templates/Petitions/fields.inc +++ b/app/templates/Petitions/fields.inc @@ -230,35 +230,37 @@ if (!empty($vv_obj?->petitioner_person?->id)) { - enrollment_flow->enrollment_flow_steps as $step): ?> - petition_step_results, "{n}[enrollment_flow_step_id=$step->id]"); - - if(!empty($result)) { - $resultLink = [ - 'controller' => 'petitions', - 'action' => 'result', - $vv_obj->id, - '?' => [ - 'enrollment_flow_step_id' => $step->id - ] - ]; - } - ?> - + petition_step_results, "{n}[enrollment_flow_step_id=$step->id]"); ?>
  • - description ?> + description ?>
    - Html->link($result[0]->comment, $resultLink) : "" ?> + comment : '' ?> +
  • +
  • +

    + +

    + element('petition/enrollmentFlowStep', ['vv_step' => $step])?> +
  • diff --git a/app/templates/element/petition/enrollmentFlowStep.php b/app/templates/element/petition/enrollmentFlowStep.php new file mode 100644 index 000000000..afc898b70 --- /dev/null +++ b/app/templates/element/petition/enrollmentFlowStep.php @@ -0,0 +1,40 @@ +plugin); +$modelName = array_pop($parsePluginName); +$elementName = lcfirst($modelName) . 'Step'; + +// The convention is that the element name for each step is the name of the EnrollmentFlow Step model followed by +// the word Step +print $this->element("petition/enrollmentFlowSteps/$elementName", ['vv_step' => $vv_step]); diff --git a/app/templates/element/petition/enrollmentFlowSteps/attributeCollectorsStep.php b/app/templates/element/petition/enrollmentFlowSteps/attributeCollectorsStep.php new file mode 100644 index 000000000..9ff02c4e3 --- /dev/null +++ b/app/templates/element/petition/enrollmentFlowSteps/attributeCollectorsStep.php @@ -0,0 +1,91 @@ +petition_attributes, '{n}.enrollment_attribute_id'); +$vv_enrollment_atttributes_ids = array_unique($vv_enrollment_atttributes_ids); + +$enrollmentAttributesTable = $this->Petition->getTable('EnrollmentAttributes'); +$vv_enrollment_attributes = $enrollmentAttributesTable->find() + ->where(fn(QueryExpression $exp, Query $q) => $exp->in('id', $vv_enrollment_atttributes_ids)) + ->toArray(); + +?> + + diff --git a/app/webroot/css/co-base.css b/app/webroot/css/co-base.css index 92584f03f..799fa3b08 100644 --- a/app/webroot/css/co-base.css +++ b/app/webroot/css/co-base.css @@ -1001,6 +1001,21 @@ ul.form-list li.alert-banner .co-alert { white-space: nowrap; margin-right: 0.5em; } +/* PETITION PREVIEW */ +a.cm-toggle { + float: right; + border: none; + background-color: transparent; +} +a.cm-toggle .material-symbols, +a.cm-toggle .material-symbols-outlined{ + color: var(--cmg-color-headings); +} +a.cm-toggle .material-symbols, +a.cm-toggle .material-symbols-outlined { + font-size: 34px; + line-height: 17px; +} /* PLATFORM NOTICE (for COmanage CO) */ #platform-notice { padding: 0.5em; diff --git a/app/webroot/js/comanage/comanage.js b/app/webroot/js/comanage/comanage.js index dd8b88aba..a15bea941 100644 --- a/app/webroot/js/comanage/comanage.js +++ b/app/webroot/js/comanage/comanage.js @@ -423,4 +423,31 @@ function setApplicationState(value, elem, reload= false) { generateFlash("" + errorThrown + " (" + jqXHR.status + ")", 'error') } }); +} + +function stepCollapseTongle(event, item) { + /** + * Toggles the expanded or collapsed state of the step element. + * + * This function prevents the default action and stops the propagation of the event, + * then toggles the "collapsed" class for the given element. It also updates + * the `aria-expanded` attribute and changes the icon displayed within the element. + * + * - If the element is collapsed, it sets `aria-expanded` to "false" and updates + * the icon to "arrow_drop_down." + * - If the element is expanded, it sets `aria-expanded` to "true" and updates + * the icon to "arrow_drop_up." + * + * @param {Event} event - The event triggered, usually by a click action. + * @param {HTMLElement} item - The DOM element being toggled that represents the step. + */ + event.preventDefault(); + event.stopPropagation(); + if ($(item).hasClass("collapsed")) { + $(item).attr("aria-expanded","false") + $(item).find('em').text("arrow_drop_down"); + } else { + $(item).attr("aria-expanded","true") + $(item).find('em').text("arrow_drop_up"); + } } \ No newline at end of file