From 3d1ad239a7919c7d550d817b791f09a8f09c3cd9 Mon Sep 17 00:00:00 2001 From: Ioannis Igoumenos Date: Sat, 16 Nov 2024 16:24:51 +0200 Subject: [PATCH 1/6] Sponsors+Managers to people picker --- .../Model/Table/EnrollmentAttributesTable.php | 4 ++ .../CoreEnroller/templates/element/field.php | 11 +++- .../templates/element/spa-field.php | 61 +++++++++++++++++++ app/src/View/Helper/FieldHelper.php | 38 ++++++++++++ .../element/form/elementFallback.php | 32 ++++++++++ app/templates/element/peopleAutocomplete.php | 5 +- .../autocomplete/cm-autocomplete-people.js | 6 +- 7 files changed, 149 insertions(+), 8 deletions(-) create mode 100644 app/plugins/CoreEnroller/templates/element/spa-field.php create mode 100644 app/templates/element/form/elementFallback.php diff --git a/app/plugins/CoreEnroller/src/Model/Table/EnrollmentAttributesTable.php b/app/plugins/CoreEnroller/src/Model/Table/EnrollmentAttributesTable.php index 3ca48ba2..ab46c269 100644 --- a/app/plugins/CoreEnroller/src/Model/Table/EnrollmentAttributesTable.php +++ b/app/plugins/CoreEnroller/src/Model/Table/EnrollmentAttributesTable.php @@ -165,6 +165,10 @@ public function initialize(array $config): void { 'type' => 'auxiliary', 'model' => 'CoSettings' ], + 'types' => [ + 'type' => 'auxiliary', + 'model' => 'Types' + ], ]); $this->setLayout([ 'index' => 'iframe', diff --git a/app/plugins/CoreEnroller/templates/element/field.php b/app/plugins/CoreEnroller/templates/element/field.php index 68e4be12..b5cd48d5 100644 --- a/app/plugins/CoreEnroller/templates/element/field.php +++ b/app/plugins/CoreEnroller/templates/element/field.php @@ -112,7 +112,12 @@ // HIDDEN Field // We print directly, we do not delegate to the element for further processing // In case this is a hidden field, we need to get only the value - $attr->hidden && $hidden =>$this->Form->hidden($formArguments['fieldName'], ['value' => $options['default']]), - // Default use case - default => $this->element('form/listItem', ['arguments' => $formArguments]) + $attr->hidden && $hidden => $this->Form->hidden($formArguments['fieldName'], ['value' => $options['default']]), + // For the case of xxx_person_id fields, we will render the People a Picker element. + str_ends_with($attr->attribute, 'person_id') => $this->element('CoreEnroller.spa-field', [ + 'vueElementName' => 'peopleAutocomplete', + 'formArguments' => $formArguments + ]), +// Default use case + default => $this->element('form/listItem', ['arguments' => $formArguments]) }; diff --git a/app/plugins/CoreEnroller/templates/element/spa-field.php b/app/plugins/CoreEnroller/templates/element/spa-field.php new file mode 100644 index 00000000..06cb1990 --- /dev/null +++ b/app/plugins/CoreEnroller/templates/element/spa-field.php @@ -0,0 +1,61 @@ + + +
  • +
    +
    +
    + + + element('form/requiredSpan') ?> + +
    + +
    + +
    + +
    + Field->constructSPAField( + // The Default field will be used to harvest the attributes + element: $this->Field->formField(...$formArguments), + // Vue/JS element + vueElementName: $vueElementName + ) ?> +
    +
    +
  • diff --git a/app/src/View/Helper/FieldHelper.php b/app/src/View/Helper/FieldHelper.php index 8fcf3ad6..f9a1a169 100644 --- a/app/src/View/Helper/FieldHelper.php +++ b/app/src/View/Helper/FieldHelper.php @@ -73,6 +73,7 @@ class FieldHelper extends Helper { * @param array $config The configuration settings provided to this helper. * * @return void + * @since COmanage Registry v5.0.0 */ public function initialize(array $config): void { @@ -94,6 +95,7 @@ public function initialize(array $config): void * @param string $fieldName * * @return array + * @since COmanage Registry v5.0.0 */ public function calculateLabelAndDescription(string $fieldName): array { @@ -180,6 +182,7 @@ public function calculateLabelAndDescription(string $fieldName): array * Calculate the list of classes for the li element * * @return string + * @since COmanage Registry v5.0.0 */ public function calculateLiClasses(): string { @@ -219,6 +222,41 @@ public function calculateLiClasses(): string return $classes; } + /** + * Construct the SPA field element + * + * @param string $fieldName The field name + * @param array $formParams The field parameters + * @param string $vueElementName The name of the JavaScript module + * + * @return string + * @since COmanage Registry v5.0.0 + */ + public function constructSPAField(string $element, string $vueElementName): string { + // Parse the ID attribute + $regexId = '/id="(.*?)"/m'; + preg_match_all($regexId, $element, $matchesId, PREG_SET_ORDER, 0); + + // Parse the Name attribute + $regexName = '/name="(.*?)"/m'; + preg_match_all($regexName, $element, $matchesName, PREG_SET_ORDER, 0); + + // Parse the Class attribute + $regexClass = '/class="(.*?)"/m'; + preg_match_all($regexClass, $element, $matchesClass, PREG_SET_ORDER, 0); + if(!empty($matchesId[0][1]) && !empty($matchesName[0][1])) { + return $this->getView()->element($vueElementName, [ + 'htmlId' => $matchesId[0][1], + 'fieldName' => $matchesName[0][1], + 'containerClasses' => $matchesClass[0][1], + 'type' => 'field' + ]); + } + + // Fallback to an error element + return $this->getView()->element('elementFallback'); + } + /** * Emit a date/time form control. * This is a wrapper function for $this->control() diff --git a/app/templates/element/form/elementFallback.php b/app/templates/element/form/elementFallback.php new file mode 100644 index 00000000..33c16a4e --- /dev/null +++ b/app/templates/element/form/elementFallback.php @@ -0,0 +1,32 @@ + + +Element ID not provided \ No newline at end of file diff --git a/app/templates/element/peopleAutocomplete.php b/app/templates/element/peopleAutocomplete.php index 7787bbf3..93666844 100644 --- a/app/templates/element/peopleAutocomplete.php +++ b/app/templates/element/peopleAutocomplete.php @@ -33,6 +33,7 @@ $htmlId = $htmlId ?? 'cmPersonPickerId'; $actionUrl = $actionUrl ?? []; // the url of the page to launch on select for a stand-alone picker $viewConfigParameters = $viewConfigParameters ?? []; + $containerClasses = $containerClasses ?? 'cm-autocomplete-container'; // Get the CSRF Token in JavaScript $token = $this->request->getAttribute('csrfToken'); @@ -132,7 +133,7 @@ } // Mount the component and provide a global reference for this app instance. - window. = app.mount("#-container"); + window. = app.mount("#-container"); -
    +
    diff --git a/app/webroot/js/comanage/components/autocomplete/cm-autocomplete-people.js b/app/webroot/js/comanage/components/autocomplete/cm-autocomplete-people.js index 990378c2..aa638856 100644 --- a/app/webroot/js/comanage/components/autocomplete/cm-autocomplete-people.js +++ b/app/webroot/js/comanage/components/autocomplete/cm-autocomplete-people.js @@ -194,8 +194,8 @@ export default { this.options.inputProps.dataPersonid = this.person.value } else if(this.options.type == 'field') { // The picker is part of a standard form field - const field = document.getElementById(this.options.fieldName); - field.value = this.person.value; + this.options.inputProps.dataPersonid = this.person.value + this.options.inputProps.value = `${this.person.label} (ID: ${this.person.value})` } else { // The picker is stand-alone, and should render the configured page in a modal on @item-select const urlForModal = this.options.actionUrl + '&person_id=' + this.person.value; @@ -249,7 +249,7 @@ export default { mounted() { if(this.options.inputValue != undefined && this.options.inputValue != '' - && this.options.htmlId == 'person_id') { + && this.options.htmlId.endsWith('person_id')) { this.options.inputProps.value = `${this.options.formParams?.fullName} (ID: ${this.options.inputValue})` } }, From c6ca0cf624485208e885f97158893daa44bcdbb9 Mon Sep 17 00:00:00 2001 From: Ioannis Igoumenos Date: Sat, 16 Nov 2024 17:33:54 +0200 Subject: [PATCH 2/6] autocomplete default label enable hiding --- app/src/View/Helper/FieldHelper.php | 4 +++- app/webroot/css/co-base.css | 7 +++++++ .../autocomplete/cm-autocomplete-people.js | 15 +++++++++++++-- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/app/src/View/Helper/FieldHelper.php b/app/src/View/Helper/FieldHelper.php index f9a1a169..dfd94a35 100644 --- a/app/src/View/Helper/FieldHelper.php +++ b/app/src/View/Helper/FieldHelper.php @@ -249,7 +249,9 @@ public function constructSPAField(string $element, string $vueElementName): stri 'htmlId' => $matchesId[0][1], 'fieldName' => $matchesName[0][1], 'containerClasses' => $matchesClass[0][1], - 'type' => 'field' + 'type' => 'field', + // we want the label to be an empty string to hide the default label introduced by the module. + 'label' => '' ]); } diff --git a/app/webroot/css/co-base.css b/app/webroot/css/co-base.css index 38865977..05012797 100644 --- a/app/webroot/css/co-base.css +++ b/app/webroot/css/co-base.css @@ -2185,6 +2185,13 @@ td .alert { bottom: 2px; margin-right: -26px; } +.co-loading-mini-container.over-input { + display: none; + position: absolute; + right: 0.5em; + bottom: 0.7em; + z-index: 100; +} #co-loading span, #co-loading-redirect span, .co-loading-mini span { diff --git a/app/webroot/js/comanage/components/autocomplete/cm-autocomplete-people.js b/app/webroot/js/comanage/components/autocomplete/cm-autocomplete-people.js index aa638856..b92bdcd5 100644 --- a/app/webroot/js/comanage/components/autocomplete/cm-autocomplete-people.js +++ b/app/webroot/js/comanage/components/autocomplete/cm-autocomplete-people.js @@ -272,11 +272,22 @@ export default { } // Otherwise return the default return this.txt['autocomplete.people.label']; + }, + hasAutoCompleteLabel: function() { + // Check to see if a label has been passed in + return this.options.label !== undefined && this.options.label !== '' + }, + getMiniLoaderClasses: function() { + if(this.options.label !== undefined && this.options.label !== '') { + return "co-loading-mini-container d-inline ms-1" + } else { + return "co-loading-mini-container d-inline ms-1 over-input" + } } }, template: ` - - + + Date: Mon, 18 Nov 2024 16:19:46 +0200 Subject: [PATCH 3/6] Internationalize the fallback element text --- app/resources/locales/en_US/field.po | 3 +++ app/templates/element/form/elementFallback.php | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/resources/locales/en_US/field.po b/app/resources/locales/en_US/field.po index f26b666d..312f3903 100644 --- a/app/resources/locales/en_US/field.po +++ b/app/resources/locales/en_US/field.po @@ -234,6 +234,9 @@ msgstr "IP Address" msgid "required" msgstr "Required" +msgid "element_fallback" +msgstr "Element ID not provided" + msgid "role_key" msgstr "Role Key" diff --git a/app/templates/element/form/elementFallback.php b/app/templates/element/form/elementFallback.php index 33c16a4e..feb18104 100644 --- a/app/templates/element/form/elementFallback.php +++ b/app/templates/element/form/elementFallback.php @@ -29,4 +29,4 @@ declare(strict_types = 1); ?> -Element ID not provided \ No newline at end of file + From c696bf42d88f7a1066428c94dc65632baedaffda Mon Sep 17 00:00:00 2001 From: Ioannis Igoumenos Date: Mon, 18 Nov 2024 19:09:42 +0200 Subject: [PATCH 4/6] Fix unable to update picker field --- app/plugins/CoreEnroller/templates/element/spa-field.php | 2 +- .../comanage/components/autocomplete/cm-autocomplete-people.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/plugins/CoreEnroller/templates/element/spa-field.php b/app/plugins/CoreEnroller/templates/element/spa-field.php index 06cb1990..d70069f9 100644 --- a/app/plugins/CoreEnroller/templates/element/spa-field.php +++ b/app/plugins/CoreEnroller/templates/element/spa-field.php @@ -1,6 +1,6 @@ Date: Mon, 18 Nov 2024 19:22:39 +0200 Subject: [PATCH 5/6] input property value to have the id on update and not only the full name --- .../autocomplete/cm-autocomplete-people.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/app/webroot/js/comanage/components/autocomplete/cm-autocomplete-people.js b/app/webroot/js/comanage/components/autocomplete/cm-autocomplete-people.js index 3ab4b1c6..209f2f16 100644 --- a/app/webroot/js/comanage/components/autocomplete/cm-autocomplete-people.js +++ b/app/webroot/js/comanage/components/autocomplete/cm-autocomplete-people.js @@ -177,7 +177,9 @@ export default { return data?.People?.map((item) => { return { "value": item.id, - "label": `${item?.primary_name?.given} ${item?.primary_name?.family}`, + // XXX The label is the value that autocomplete will use to update the input field value property. + "label": `${item?.primary_name?.given} ${item?.primary_name?.family} (ID: ${item?.id})`, + "fullName": `${item?.primary_name?.given} ${item?.primary_name?.family}`, "itemId": `${item?.id}`, "email": this.filterByEmailAddressType(item?.email_addresses), "emailPretty": this.shortenString(this.constructEmailCsv(this.filterByEmailAddressType(item?.email_addresses))), @@ -190,13 +192,8 @@ export default { }) }, setPerson() { - if(this.options.type == 'default') { + if(['default', 'field'].includes(this.options.type)) { this.options.inputProps.dataPersonid = this.person.value - } else if(this.options.type == 'field') { - // The picker is part of a standard form field - const field = document.getElementById(this.options.fieldName); - this.options.inputProps.dataPersonid = this.person.value - field.value = `${this.person.label} (ID: ${this.person.value})` } else { // The picker is stand-alone, and should render the configured page in a modal on @item-select const urlForModal = this.options.actionUrl + '&person_id=' + this.person.value; @@ -312,8 +309,9 @@ export default {
    - - + + + {{ this.txt['GroupMembers'] }}
    From 9a713832303de0ef6dcaa84b6e3d0f4d29f5935d Mon Sep 17 00:00:00 2001 From: Ioannis Igoumenos Date: Mon, 18 Nov 2024 19:26:24 +0200 Subject: [PATCH 6/6] Fix method signature --- app/src/View/Helper/FieldHelper.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/View/Helper/FieldHelper.php b/app/src/View/Helper/FieldHelper.php index dfd94a35..90d6c0de 100644 --- a/app/src/View/Helper/FieldHelper.php +++ b/app/src/View/Helper/FieldHelper.php @@ -225,9 +225,8 @@ public function calculateLiClasses(): string /** * Construct the SPA field element * - * @param string $fieldName The field name - * @param array $formParams The field parameters - * @param string $vueElementName The name of the JavaScript module + * @param string $element HTML element created with the CAKEPHP HTML Helper + * @param string $vueElementName The name of the JavaScript module * * @return string * @since COmanage Registry v5.0.0