From ea2e397ab2f9294a5b817bb0105875ae89bbdc75 Mon Sep 17 00:00:00 2001 From: Ioannis Igoumenos Date: Tue, 28 Jan 2025 10:58:30 +0200 Subject: [PATCH] Save petition attribute collection data Save form and display.php render phpv8.2 deprecation Petition preview parse people picker value Petition Preview new structure Add collapsable behavior fix people link Fix disabled fields. Fix affiliation_type petition render. More improvements Fixing Petition resume view --- .../AttributeCollectorsController.php | 17 +++- .../Model/Table/AttributeCollectorsTable.php | 24 ++++- .../Model/Table/PetitionAttributesTable.php | 1 + .../CoreEnroller/src/config/plugin.json | 3 +- .../templates/AttributeCollectors/display.php | 8 ++ .../templates/EnrollmentAttributes/fields.inc | 3 +- .../CoreEnroller/templates/element/field.php | 2 +- .../element/mveas/fieldset-field.php | 30 ++++++ app/src/Model/Table/PetitionsTable.php | 6 +- app/src/View/Helper/FieldHelper.php | 2 +- app/src/View/Helper/PetitionHelper.php | 1 + app/templates/Petitions/fields.inc | 38 ++++---- .../element/petition/enrollmentFlowStep.php | 40 ++++++++ .../attributeCollectorsStep.php | 91 +++++++++++++++++++ app/webroot/css/co-base.css | 15 +++ app/webroot/js/comanage/comanage.js | 27 ++++++ 16 files changed, 276 insertions(+), 32 deletions(-) create mode 100644 app/plugins/CoreEnroller/templates/AttributeCollectors/display.php create mode 100644 app/templates/element/petition/enrollmentFlowStep.php create mode 100644 app/templates/element/petition/enrollmentFlowSteps/attributeCollectorsStep.php 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