From 3f1629fdbec022874ed261b114d0eef17d7f9df0 Mon Sep 17 00:00:00 2001 From: Arlen Johnson Date: Sun, 10 Sep 2023 07:20:37 -0400 Subject: [PATCH 1/2] Provide read-only output for External Identity "view" action (CFM-319) --- app/resources/locales/en_US/information.po | 6 + .../Model/Table/ExternalIdentitiesTable.php | 11 ++ app/src/View/Helper/FieldHelper.php | 147 ++++++++++-------- app/templates/AdHocAttributes/fields.inc | 3 +- app/templates/Addresses/fields.inc | 3 +- app/templates/EmailAddresses/fields.inc | 3 +- app/templates/ExternalIdentities/columns.inc | 1 + app/templates/ExternalIdentities/fields.inc | 3 +- .../ExternalIdentityRoles/columns.inc | 1 + .../ExternalIdentityRoles/fields.inc | 3 +- app/templates/Identifiers/fields.inc | 3 +- app/templates/Names/fields.inc | 3 +- app/templates/Pronouns/fields.inc | 3 +- app/templates/TelephoneNumbers/fields.inc | 3 +- app/templates/Urls/fields.inc | 3 +- app/templates/element/mveaCanvas.php | 37 +++-- app/templates/element/mveaJs.php | 5 +- app/templates/element/subnavigation.php | 23 +-- .../js/comanage/components/mvea/mvea-item.js | 2 +- 19 files changed, 143 insertions(+), 120 deletions(-) diff --git a/app/resources/locales/en_US/information.po b/app/resources/locales/en_US/information.po index f129fe850..e92f76aef 100644 --- a/app/resources/locales/en_US/information.po +++ b/app/resources/locales/en_US/information.po @@ -39,6 +39,12 @@ msgstr "Please select the collaboration (CO) you wish to manage." msgid "entity.id" msgstr "ID: {0}" +msgid "noattrs" +msgstr "No attributes" + +msgid "notset" +msgstr "not set" + msgid "pagination.format" msgstr "Page {{page}} of {{pages}}, Viewing {{start}}-{{end}} of {{count}}" diff --git a/app/src/Model/Table/ExternalIdentitiesTable.php b/app/src/Model/Table/ExternalIdentitiesTable.php index 986300d14..cb8842111 100644 --- a/app/src/Model/Table/ExternalIdentitiesTable.php +++ b/app/src/Model/Table/ExternalIdentitiesTable.php @@ -121,6 +121,17 @@ public function initialize(array $config): void { 'Urls' ]); $this->setIndexContains(['PrimaryName']); + $this->setViewContains([ + 'PrimaryName', + 'Addresses', + 'AdHocAttributes', + 'EmailAddresses', + 'Identifiers', + 'Names', + 'Pronouns', + 'TelephoneNumbers', + 'Urls' + ]); $this->setAutoViewVars([ 'statuses' => [ diff --git a/app/src/View/Helper/FieldHelper.php b/app/src/View/Helper/FieldHelper.php index b9f31c759..3ef88ee7b 100644 --- a/app/src/View/Helper/FieldHelper.php +++ b/app/src/View/Helper/FieldHelper.php @@ -191,76 +191,95 @@ public function control(string $fieldName, */ public function dateControl(string $fieldName, string $dateType=DateTypeEnum::Standard): string { - // A datetime field will be rendered as a plain text input with adjacent date and time pickers - // that will interact with the field value. Allowing direct access to the input field is for - // accessibility purposes. - - $pickerType = $dateType; - // Special-case the very common "valid_from" and "valid_through" fields so we won't need - // to specify their types in fields.inc. - if($fieldName == 'valid_from') { - $pickerType = DateTypeEnum::FromTime; - } - if($fieldName == 'valid_through') { - $pickerType = DateTypeEnum::ThroughTime; - } - - // Append the timezone to the label -- TODO: see that the timezone gets output to the display - $label = __d('field', $fieldName.".tz", [$this->_View->get('vv_tz')]); - - // Create the options array for the (text input) form control - $coptions = []; - $coptions['class'] = 'form-control datepicker'; - - if($pickerType == DateTypeEnum::DateOnly) { - $coptions['placeholder'] = 'YYYY-MM-DD'; - $coptions['pattern'] = '\d{4}-\d{2}-\d{2}'; - $coptions['title'] = __d('field', 'datepicker.enterDate'); + if($this->action == 'view') { + // return the date as plaintext + $coptions = []; + $entity = $this->getView()->get('vv_obj'); + if (!empty($entity->$fieldName)) { + // Adjust the time back to the user's timezone + if ($dateType == DateTypeEnum::DateOnly) { + $controlCode = ''; + } else { + $controlCode = ''; + } + } else { + $controlCode = __d('information', 'notset'); + } + // Return this to the generic control() function + return $this->control($fieldName, $coptions, ctrlCode: $controlCode, labelIsTextOnly: true); + } else { - $coptions['placeholder'] = 'YYYY-MM-DD HH:MM:SS'; - $coptions['pattern'] = '\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}'; - $coptions['title'] = __d('field', 'datepicker.enterDateTime'); - } - $coptions['id'] = str_replace("_", "-", $fieldName); + // A datetime field will be rendered as a plain text input with adjacent date and time pickers + // that will interact with the field value. Allowing direct access to the input field is for + // accessibility purposes. + + $pickerType = $dateType; + // Special-case the very common "valid_from" and "valid_through" fields so we won't need + // to specify their types in fields.inc. + if ($fieldName == 'valid_from') { + $pickerType = DateTypeEnum::FromTime; + } + if ($fieldName == 'valid_through') { + $pickerType = DateTypeEnum::ThroughTime; + } - $entity = $this->getView()->get('vv_obj'); + // Append the timezone to the label -- TODO: see that the timezone gets output to the display + $label = __d('field', $fieldName . ".tz", [$this->_View->get('vv_tz')]); - // Default the picker date to today - $now = FrozenTime::now(); - $pickerDate = $now->i18nFormat('yyyy-MM-dd'); - - // Get the existing values, if present - if(!empty($entity->$fieldName)) { - // Adjust the time back to the user's timezone - if($pickerType == DateTypeEnum::DateOnly) { - $coptions['value'] = $entity->$fieldName->i18nFormat("yyyy-MM-dd", $this->getView()->get('vv_tz')); + // Create the options array for the (text input) form control + $coptions = []; + $coptions['class'] = 'form-control datepicker'; + + if ($pickerType == DateTypeEnum::DateOnly) { + $coptions['placeholder'] = 'YYYY-MM-DD'; + $coptions['pattern'] = '\d{4}-\d{2}-\d{2}'; + $coptions['title'] = __d('field', 'datepicker.enterDate'); } else { - $coptions['value'] = $entity->$fieldName->i18nFormat("yyyy-MM-dd HH:mm:ss", $this->getView()->get('vv_tz')); + $coptions['placeholder'] = 'YYYY-MM-DD HH:MM:SS'; + $coptions['pattern'] = '\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}'; + $coptions['title'] = __d('field', 'datepicker.enterDateTime'); } - $pickerDate = $entity->$fieldName->i18nFormat("yyyy-MM-dd", $this->getView()->get('vv_tz')); - } - - // Set the date picker floor year value (-100 years) - $pickerDateFT = new FrozenTime($pickerDate); - $pickerDateFT = $pickerDateFT->subYears(100); - $pickerFloor = $pickerDateFT->i18nFormat("yyyy-MM-dd"); - - $date_picker_args = [ - 'fieldName' => $fieldName, - 'pickerDate' => $pickerDate, - 'pickerType' => $pickerType, - 'pickerFloor' => $pickerFloor - ]; - - // Create a text field to hold our value and call the datePicker - $controlCode = $this->Form->text($fieldName, $coptions) - . $this->getView()->element('datePicker', $date_picker_args); + $coptions['id'] = str_replace("_", "-", $fieldName); - // Specify a class on the
  • form control wrapper - $liClass = "fields-datepicker"; - - // Pass everything to the generic control() function - return $this->control($fieldName, $coptions, ctrlCode: $controlCode, cssClass: $liClass); + $entity = $this->getView()->get('vv_obj'); + + // Default the picker date to today + $now = FrozenTime::now(); + $pickerDate = $now->i18nFormat('yyyy-MM-dd'); + + // Get the existing values, if present + if(!empty($entity->$fieldName)) { + // Adjust the time back to the user's timezone + if($pickerType == DateTypeEnum::DateOnly) { + $coptions['value'] = $entity->$fieldName->i18nFormat("yyyy-MM-dd", $this->getView()->get('vv_tz')); + } else { + $coptions['value'] = $entity->$fieldName->i18nFormat("yyyy-MM-dd HH:mm:ss", $this->getView()->get('vv_tz')); + } + $pickerDate = $entity->$fieldName->i18nFormat("yyyy-MM-dd", $this->getView()->get('vv_tz')); + } + + // Set the date picker floor year value (-100 years) + $pickerDateFT = new FrozenTime($pickerDate); + $pickerDateFT = $pickerDateFT->subYears(100); + $pickerFloor = $pickerDateFT->i18nFormat("yyyy-MM-dd"); + + $date_picker_args = [ + 'fieldName' => $fieldName, + 'pickerDate' => $pickerDate, + 'pickerType' => $pickerType, + 'pickerFloor' => $pickerFloor + ]; + + // Create a text field to hold our value and call the datePicker + $controlCode = $this->Form->text($fieldName, $coptions) + . $this->getView()->element('datePicker', $date_picker_args); + + // Specify a class on the
  • form control wrapper + $liClass = "fields-datepicker"; + + // Pass everything to the generic control() function + return $this->control($fieldName, $coptions, ctrlCode: $controlCode, cssClass: $liClass); + } } /** diff --git a/app/templates/AdHocAttributes/fields.inc b/app/templates/AdHocAttributes/fields.inc index 6a66210f0..ab89d16e6 100644 --- a/app/templates/AdHocAttributes/fields.inc +++ b/app/templates/AdHocAttributes/fields.inc @@ -25,8 +25,7 @@ * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ -// This view does not currently support read-only -if($vv_action == 'add' || $vv_action == 'edit') { +if($vv_action == 'add' || $vv_action == 'edit' || $vv_action == 'view') { print $this->Field->control('tag'); print $this->Field->control('value'); diff --git a/app/templates/Addresses/fields.inc b/app/templates/Addresses/fields.inc index 63c9a8703..1e0522e2b 100644 --- a/app/templates/Addresses/fields.inc +++ b/app/templates/Addresses/fields.inc @@ -25,8 +25,7 @@ * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ -// This view does not currently support read-only -if($vv_action == 'add' || $vv_action == 'edit') { +if($vv_action == 'add' || $vv_action == 'edit' || $vv_action == 'view') { // Dynamic required fields is automatically handled by FormHelper via the // validation rules diff --git a/app/templates/EmailAddresses/fields.inc b/app/templates/EmailAddresses/fields.inc index d5790a145..0c2b259e8 100644 --- a/app/templates/EmailAddresses/fields.inc +++ b/app/templates/EmailAddresses/fields.inc @@ -25,8 +25,7 @@ * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ -// This view does currently not support read-only -if($vv_action == 'add' || $vv_action == 'edit') { +if($vv_action == 'add' || $vv_action == 'edit' || $vv_action == 'view') { print $this->Field->control('mail'); print $this->Field->control('type_id', ['default' => $vv_default_type]); diff --git a/app/templates/ExternalIdentities/columns.inc b/app/templates/ExternalIdentities/columns.inc index 5ed7c1df5..6a516d069 100644 --- a/app/templates/ExternalIdentities/columns.inc +++ b/app/templates/ExternalIdentities/columns.inc @@ -30,6 +30,7 @@ $indexColumns = [ 'name' => [ 'type' => 'link', + 'action' => 'view', 'model' => 'primary_name', 'field' => 'full_name', // XXX see comments in the controller about sorting on given vs family diff --git a/app/templates/ExternalIdentities/fields.inc b/app/templates/ExternalIdentities/fields.inc index 45904c2a1..8dd51e262 100644 --- a/app/templates/ExternalIdentities/fields.inc +++ b/app/templates/ExternalIdentities/fields.inc @@ -25,8 +25,7 @@ * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ -// This view does not currently support read-only -if($vv_action == 'add' || $vv_action == 'edit') { +if($vv_action == 'add' || $vv_action == 'edit' || $vv_action == 'view') { // XXX sync status? print $this->Field->control('status', ['empty' => false]); diff --git a/app/templates/ExternalIdentityRoles/columns.inc b/app/templates/ExternalIdentityRoles/columns.inc index 751584bbd..a925abfbe 100644 --- a/app/templates/ExternalIdentityRoles/columns.inc +++ b/app/templates/ExternalIdentityRoles/columns.inc @@ -30,6 +30,7 @@ $indexColumns = [ 'title' => [ 'type' => 'link', + 'action' => 'view', 'sortable' => true ], 'affiliation_type_id' => [ diff --git a/app/templates/ExternalIdentityRoles/fields.inc b/app/templates/ExternalIdentityRoles/fields.inc index d1301089d..abab0817b 100644 --- a/app/templates/ExternalIdentityRoles/fields.inc +++ b/app/templates/ExternalIdentityRoles/fields.inc @@ -25,8 +25,7 @@ * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ -// This view does not currently support read-only -if($vv_action == 'add' || $vv_action == 'edit') { +if($vv_action == 'add' || $vv_action == 'edit' || $vv_action == 'view') { print $this->Field->control('affiliation_type_id', labelText: __d('field', 'affiliation')); print $this->Field->control('status', ['empty' => false]); diff --git a/app/templates/Identifiers/fields.inc b/app/templates/Identifiers/fields.inc index 17f7ea380..93b2bece9 100644 --- a/app/templates/Identifiers/fields.inc +++ b/app/templates/Identifiers/fields.inc @@ -25,8 +25,7 @@ * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ -// This view does not currently support read-only -if($vv_action == 'add' || $vv_action == 'edit') { +if($vv_action == 'add' || $vv_action == 'edit' || $vv_action == 'view') { print $this->Field->control('identifier'); print $this->Field->control('type_id', ['default' => $vv_default_type]); diff --git a/app/templates/Names/fields.inc b/app/templates/Names/fields.inc index 275f26e33..ce0695378 100644 --- a/app/templates/Names/fields.inc +++ b/app/templates/Names/fields.inc @@ -25,8 +25,7 @@ * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ -// This view does not currently support read-only -if($vv_action == 'add' || $vv_action == 'edit') { +if($vv_action == 'add' || $vv_action == 'edit' || $vv_action == 'view') { // Dynamic required fields is automatically handled by FormHelper via the // validation rules, but we need to manually check permitted fields. diff --git a/app/templates/Pronouns/fields.inc b/app/templates/Pronouns/fields.inc index 26d64e1a4..2afa0daf0 100644 --- a/app/templates/Pronouns/fields.inc +++ b/app/templates/Pronouns/fields.inc @@ -25,8 +25,7 @@ * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ -// This view does currently not support read-only -if($vv_action == 'add' || $vv_action == 'edit') { +if($vv_action == 'add' || $vv_action == 'edit' || $vv_action == 'view') { print $this->Field->control('pronouns'); print $this->Field->control('type_id', ['default' => $vv_default_type]); diff --git a/app/templates/TelephoneNumbers/fields.inc b/app/templates/TelephoneNumbers/fields.inc index 058b2172a..d496cc45b 100644 --- a/app/templates/TelephoneNumbers/fields.inc +++ b/app/templates/TelephoneNumbers/fields.inc @@ -25,8 +25,7 @@ * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ -// This view does not currently support read-only -if($vv_action == 'add' || $vv_action == 'edit') { +if($vv_action == 'add' || $vv_action == 'edit' || $vv_action == 'view') { // Dynamic required fields is automatically handled by FormHelper via the // validation rules, but we need to manually check permitted fields. diff --git a/app/templates/Urls/fields.inc b/app/templates/Urls/fields.inc index f3d442389..fd20eb8c1 100644 --- a/app/templates/Urls/fields.inc +++ b/app/templates/Urls/fields.inc @@ -25,8 +25,7 @@ * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ -// This view does currently not support read-only -if($vv_action == 'add' || $vv_action == 'edit') { +if($vv_action == 'add' || $vv_action == 'edit' || $vv_action == 'view') { print $this->Field->control('url'); print $this->Field->control('type_id', ['default' => $vv_default_type]); diff --git a/app/templates/element/mveaCanvas.php b/app/templates/element/mveaCanvas.php index 7da504939..61e30b6d0 100644 --- a/app/templates/element/mveaCanvas.php +++ b/app/templates/element/mveaCanvas.php @@ -69,7 +69,7 @@ ?>

    - +
    element('menuAction', $action_args) ?>
    @@ -92,22 +92,25 @@ ?>
    - element( - 'mveaJs', - [ - 'htmlId' => 'mvea-canvas-' . $attr . '-js', - 'parentId' => $objId, - 'mveaType' => $attr, - 'entityType' => $vv_entity_type - ] - ); + +
    + + element( + 'mveaJs', + [ + 'htmlId' => 'mvea-canvas-' . $attr . '-js', + 'parentId' => $objId, + 'mveaType' => $attr, + 'entityType' => $vv_entity_type + ] + ); + } } - } - // TODO: Add the DOB as its own special card (CFM-261) - print $this->element('mveaModal'); - ?> + ?> + + element('mveaModal') ?>
    \ No newline at end of file diff --git a/app/templates/element/mveaJs.php b/app/templates/element/mveaJs.php index 23533eda9..bb8511dcd 100644 --- a/app/templates/element/mveaJs.php +++ b/app/templates/element/mveaJs.php @@ -29,7 +29,7 @@ $htmlId = $htmlId; $parentId = $parentId; $mveaType = $mveaType; // the type of MVEA we will fetch -$entityType = $entityType; // the type of entity continaing the MVEA (person, person_role, external_identity) +$entityType = $entityType; // the type of entity continaing the MVEA (person, person_role, external_identity, external_identity_role) // Get the camel-case controller name and generate the title $mveaController = Cake\Utility\Inflector::camelize($mveaType); @@ -63,7 +63,8 @@ mveaType: '', mveaController: '', mveaTitle: '', - webroot: 'request->getAttribute('webroot') ?>' + webroot: 'request->getAttribute('webroot') ?>', + action: '' }, txt: JSON.parse('locales()) ?>'), isLoading: true diff --git a/app/templates/element/subnavigation.php b/app/templates/element/subnavigation.php index 6c1f79f81..37dd3f52e 100644 --- a/app/templates/element/subnavigation.php +++ b/app/templates/element/subnavigation.php @@ -204,8 +204,9 @@ print $this->Html->link( __d('controller', 'People', [1]), [ 'controller' => 'people', - // TODO: the following test needs to be made based on read-only status of the Person - 'action' => $curAction == 'view' ? 'view' : 'edit', + // TODO: the following test needs to be made based on read-only status of the Person only + //'action' => $curAction == 'view' ? 'view' : 'edit', + 'action' => 'edit', $curId ], ['class' => $linkClass] @@ -323,26 +324,16 @@
  • Html->link( __d('controller', 'Properties', [99]), [ 'controller' => $cc, - 'action' => 'edit', + 'action' => 'view', $cid ], ['class' => $linkClass] diff --git a/app/webroot/js/comanage/components/mvea/mvea-item.js b/app/webroot/js/comanage/components/mvea/mvea-item.js index 611a5aa04..1eb4d841c 100644 --- a/app/webroot/js/comanage/components/mvea/mvea-item.js +++ b/app/webroot/js/comanage/components/mvea/mvea-item.js @@ -36,7 +36,7 @@ export default { }, computed: { mveaLink: function() { - return this.core.webroot + this.core.mveaController + '/edit/' + this.mvea.id; + return this.core.webroot + this.core.mveaController + (this.core.action == 'edit' ? '/edit/' : '/view/') + this.mvea.id; } }, methods: { From 7e4a26095c61882fde46f09ad6675cf3d975bb5e Mon Sep 17 00:00:00 2001 From: Arlen Johnson Date: Wed, 13 Sep 2023 16:25:51 -0400 Subject: [PATCH 2/2] Color contrast updates for disabled select boxes in Dark Mode (CFM-319) --- app/webroot/css/co-base.css | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/webroot/css/co-base.css b/app/webroot/css/co-base.css index 331af0b29..7742a527c 100644 --- a/app/webroot/css/co-base.css +++ b/app/webroot/css/co-base.css @@ -691,11 +691,14 @@ ul.form-list li.alert-banner .co-alert { .cm-subnav-tabs .nav-link { text-transform: uppercase; padding: 1em 1.5em; - color: var(--cmg-color-link); + color: var(--cmg-color-link) !important; +} +.cm-subnav-links .nav-link { + color: var(--cmg-color-link) !important; } .cm-subnav-tabs .nav-link.active, .cm-subnav-links .nav-link.active { - color: var(--cmg-color-body-txt); + color: var(--cmg-color-body-txt) !important; background-color: var(--cmg-color-body-bg); border-color: var(--cmg-color-bg-006) var(--cmg-color-bg-006) var(--cmg-color-body-bg) var(--cmg-color-bg-006); } @@ -1270,6 +1273,9 @@ ul.form-list select { background-color: var(--cmg-color-body-bg); border-color: var(--cmg-color-bg-007); } +.form-select:disabled { + background-color: var(--cmg-color-bg-009); +} ul.form-list li.fields-submit .required { font-style: italic; }