Skip to content

Feature cfm150 autocomplete #167

Merged
merged 38 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
1999c79
Autocomplete widget added for selecting a Group member (CFM-150) (#164)
arlen Mar 6, 2024
fc0fdc4
add primevue autocomplete library dependency
Ioannis Mar 10, 2024
b0068fe
Improve/cleanup backend block search functionality
Ioannis Mar 10, 2024
66839d8
Decloupe where clause construction from join clause construction
Ioannis Mar 10, 2024
2dbc1a2
Improve filtering.Dynamically construct where clause using QueryExpre…
Ioannis Mar 10, 2024
060dfe6
Introduce IndexQueryTrait
Ioannis Mar 10, 2024
aa73e23
fix broken mveaType query.Improve Changelog.
Ioannis Mar 10, 2024
1311315
first get request
Ioannis Mar 10, 2024
a8ba9c9
add CoSettings PeoplePicker Configuration
Ioannis Mar 11, 2024
c0305b9
fix condition
Ioannis Mar 12, 2024
8b061f1
Improve FieldHelper
Ioannis Mar 12, 2024
17f32c7
Properly align grouped html controls
Ioannis Mar 12, 2024
4a805f8
Add type to emails and identifiers
Ioannis Mar 12, 2024
72171d4
Add loader.Improve fetch response handling
Ioannis Mar 13, 2024
bf41aa5
Added loader. Fixed duplicates.
Ioannis Mar 13, 2024
0d06b3d
typo fix
Ioannis Mar 13, 2024
a18c993
add filtering with given and family name. Fetch only active users.
Ioannis Mar 13, 2024
0954ba4
refactor frontend error handling
Ioannis Mar 13, 2024
941ffd2
add subfield-col css rule
Ioannis Mar 13, 2024
86fe75b
Peoplepikcer enum
Ioannis Mar 14, 2024
c8a0104
Provide access to configurations locally and globally.Improve fetch i…
Ioannis Mar 15, 2024
238de1a
fix url string
Ioannis Mar 15, 2024
0b3dec0
fix provide/inject functionality
Ioannis Mar 15, 2024
4acb787
Add a subcomponent for item-with-type and style things for easier vis…
arlen Mar 15, 2024
567d656
highlight query string
Ioannis Mar 15, 2024
f4009bb
highlighting fix
Ioannis Mar 15, 2024
a0ab929
sort methods by name
Ioannis Mar 15, 2024
af96643
Add item-id to autocomplete label and update color file (CFM-150)
arlen Mar 15, 2024
f885ca9
Add pager link "show more" to autocomplete (CFM-150)
arlen Mar 15, 2024
f02eaee
Fix label id reference for autocomplete field (CFM-150)
arlen Mar 15, 2024
134c18f
Implement pagination
Ioannis Mar 15, 2024
04a8bb2
filter the active GroupMembers
Ioannis Mar 16, 2024
e5f710a
Refactor GroupMembersTable::isMember Query construction
Ioannis Mar 16, 2024
d8eae4f
Update Group Member listing to expose add / edit / view in a modal wi…
arlen Mar 19, 2024
a8c32b0
Move the person picker to the index of the Group Member list and laun…
arlen Mar 21, 2024
123702d
Add scrolling to the autocomplete people picker (CFM-150)
arlen Mar 21, 2024
2ee562c
removed trailing semi colon
Ioannis Mar 21, 2024
c1c0f69
Change default modal title (CFM-150)
arlen Mar 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions app/resources/locales/en_US/operation.po
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ msgstr "Bulk add"
msgid "add.member"
msgstr "Add member: "

msgid "add.owner"
msgstr "Add owner: "

msgid "autocomplete.pager.show.more"
msgstr "show more"

Expand Down
22 changes: 22 additions & 0 deletions app/src/Controller/GroupMembersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,26 @@ public function beforeRender(EventInterface $event) {

return parent::beforeRender($event);
}

/**
* Handle an add action for a Group Member.
*
* @since COmanage Registry v5.0.0
*/

public function add() {
// If we have a person_id in the request, the person has been pre-selected.
if(!empty($this->request->getQuery('person_id'))) {
$personId = $this->request->getQuery('person_id');
$Names = $this->getTableLocator()->get('Names');
$personName = $Names->primaryName((int)$personId)->full_name;
$selectedPerson = [
'id' => $personId,
'name' => $personName
];
$this->set('vv_selected_person', $selectedPerson);
}

return parent::add();
}
}
9 changes: 5 additions & 4 deletions app/src/View/Helper/FieldHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -590,14 +590,14 @@ protected function formNameDiv(string $fieldName,
*
* @param string $fieldName Field name of input field
* @param array $viewConfigParameters
* @param string $type Type of person autocomplete to use (XXX should be an enum, and a default should be set)
* @param string $personType Type of person autocomplete to use (XXX should be an enum, and a default should be set)
*
* @return string Source HTML
* @since COmanage Registry v5.0.0
*
*/

public function peopleAutocompleteControl(string $fieldName, array $viewConfigParameters = [], string $type = 'coperson'): string {
public function peopleAutocompleteControl(string $fieldName, array $viewConfigParameters = [], string $personType = 'coperson'): string {
if($this->action == 'view') {
// return the member name value as plaintext
$coptions = ['type' => 'text'];
Expand Down Expand Up @@ -632,15 +632,16 @@ public function peopleAutocompleteControl(string $fieldName, array $viewConfigPa
$this->Form->unlockField($autoCompleteFieldName);

$autocompleteArgs = [
'type' => 'field',
'fieldName' => $fieldName,
'type' => $type,
'personType' => $personType,
'htmlId' => $autoCompleteFieldName,
'viewConfigParameters' => $viewConfigParameters
];

// Create a hidden field to hold our value and emit the autocomplete widget
$controlCode = $this->Form->hidden($fieldName, $coptions)
. $this->getView()->element('autocompletePeople', $autocompleteArgs);
. $this->getView()->element('peopleAutocomplete', $autocompleteArgs);

// XXX the numeric value passed to 'autocomplete.people.desc' should be derived from config; it is the minLength value for starting autocomplete.
$autoCompleteDesc = '<div class="field-desc"><span class="material-icons">info</span> ' . __d('operation','autocomplete.people.desc',['2']) . '</div>';
Expand Down
4 changes: 4 additions & 0 deletions app/src/View/Helper/VueHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,12 @@
class VueHelper extends Helper {
private array $locales_list = [
'controller' => [
['GroupMembers', 1],
['Identifiers', 1]
],
'default' => [
'registry.meta.registry'
],
'enumeration' => [
'SuspendableStatusEnum.S'
],
Expand Down
29 changes: 19 additions & 10 deletions app/templates/GroupMembers/columns.inc
Original file line number Diff line number Diff line change
Expand Up @@ -62,24 +62,25 @@ $indexColumns = [
];

// Suppress the default add link
$suppressAddLink = true;
// XXX We are temporarily overriding the default "Add" link - it will be replaced with the autocomplete people picker
// $topLinks appear as an upper right menu
$suppressAddLink = true;
$topLinks = [
/*
// This "Add" link launches the add form in a modal with a autocomplete people picker as a field.
// Leave it here as a reference until we have a similar field such as "sponsor" created.
[
'icon' => 'Add',
'order' => 'Default',
'label' => __d('operation', 'add.a', [__d('controller', 'GroupMembers', 1)]),
'link' => [
'controller' => 'GroupMembers',
'action' => 'add',
$vv_obj->id
'action' => 'add'
],
'class' => 'cm-modal-link nospin',
'dataAttrs' => [
['data-cm-modal-title', __d('controller', 'GroupMembers', 1)]
]
]
*/
];

/*
Expand All @@ -96,11 +97,19 @@ $subnav = [
];

// Page options
/*
$peoplePicker = [
'actionUrl' => 'url',
'htmlId' => 'memberpicker',
'label' => __d('operation','add.member'),
'type' => 'add' // can be 'add' or 'field'
'viewConfigParameters' => [
'for' => 'GroupMembers',
'action' => $vv_action,
'groupId' => $this->getRequest()?->getQuery('group_id')
],
'actionUrl' => [
'plugin' => null,
'controller' => 'GroupMembers',
'action' => 'add',
'?' => [
'group_id' => $this->getRequest()?->getQuery('group_id')
]
]
];
*/
38 changes: 32 additions & 6 deletions app/templates/GroupMembers/fields.inc
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,38 @@
*/

if($vv_action == 'add') {
// Produce the autocomplete people selector on 'add'
print $this->Field->peopleAutocompleteControl('person_id', [
'for' => 'GroupMembers',
'action' => $vv_action,
'groupId' => $this->getRequest()?->getQuery('group_id')
]);
if(!empty($vv_selected_person)) {
// The person has been preselected. Created a hidden field, and present information about the person.
print $this->Form->hidden('person_id', ['value' => $vv_selected_person['id']]);

// Present the person information in the view:
?>
<li>
<div class="field">
<div class="field-name">
<div class="field-title">
<?= __d('field','name') ?>
</div>
</div>
<div class="field-info">
<span class="group-member-to-add-name">
<?= $vv_selected_person['name'] ?>
</span>
<span class="group-member-to-add-id">
(<?= __d('information', 'entity.id', [$vv_selected_person['id']]) ?>)
</span>
</div>
</div>
</li>
<?php
} else {
// Produce the autocomplete people selector on 'add'
print $this->Field->peopleAutocompleteControl('person_id', [
'for' => 'GroupMembers',
'action' => $vv_action,
'groupId' => $this->getRequest()?->getQuery('group_id')
]);
}

// XXX As a temporary hack for development, we accept a manually entered Person ID
// XXX leave here temporarily.
Expand Down
9 changes: 5 additions & 4 deletions app/templates/element/menuAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
*/

$actionsCount = count($vv_actions);
$actionsCount = count($vv_actions) + (!empty($vv_people_picker) ? 1 : 0);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try this

count($vv_actions) + (int)!empty($vv_people_picker);

instead

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great improvement - changed!

$actionsCountClass = $actionsCount > 0 ? ' actions-count-' . $actionsCount : '';
$actionsExpandedClass = ($actionsCount > 0 && $actionsCount < 4) ? ' actions-expanded' : '';
$actionsMenuClass = (!empty($vv_actions_class) ? $vv_actions_class : 'field-actions-menu')
Expand Down Expand Up @@ -64,12 +64,13 @@ class="<?= $actionsMenuClass; ?>">
<ul id="action-list_<?= $actionsMenuUid; ?>" class="dropdown-menu nospin">
<?php if(!empty($vv_people_picker)):?>
<li class="action-list-item">
<!-- XXX This is a stub for further development -->
<?= $this->element('autocompletePeople', ['vv_picker_options' => $vv_people_picker]); ?>
<div id="cm-people-picker">
<?= $this->element('peopleAutocomplete', $vv_people_picker); ?>
</div>
</li>
<?php endif; ?>
<?php foreach($vv_actions as $action): ?>
<?php
<?php
$actionUrl = $this->Url->build($action['url']);
$actionDataAttrs = '';
if(!empty($action['dataAttrs'])) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* COmanage Registry People Autocomplete Vue.js Component
* COmanage Registry People Autocomplete Vue.js component field for forms
*
* Portions licensed to the University Corporation for Advanced Internet
* Development, Inc. ("UCAID") under one or more contributor license agreements.
Expand All @@ -26,15 +26,24 @@
*/

// Get parameters
$fieldName = $fieldName ?? '';
$type = $type ?? '';
$htmlId = $htmlId ?? '';
$type = $type ?? 'stand-alone'; // autocomplete person picker type: 'stand-alone' or 'field', defaults to 'stand-alone'.
$label = $label ?? __d('operation','autocomplete.people.label');
$fieldName = $fieldName ?? 'person_id';
$personType = $personType ?? 'coperson';
$htmlId = $htmlId ?? 'cmPersonPickerId';
$actionUrl = $actionUrl ?? []; // the url of the page to launch on select for a stand-alone picker
$viewConfigParameters = $viewConfigParameters ?? [];

// Get the CSRF Token in JavaScript
$token = $this->request->getAttribute('csrfToken');
// Load my helper functions
$vueHelper = $this->loadHelper('Vue');

// If we have the $actionUrl array, construct the URL
$constructedActionUrl = '';
if(!empty($actionUrl)) {
$constructedActionUrl = $this->Url->build($actionUrl);
}

// Create a people autocomplete text input.
?>
Expand Down Expand Up @@ -65,10 +74,13 @@
data() {
return {
autocompleteOptions: {
label: '<?= $label ?>',
fieldName: '<?= $fieldName ?>',
type: '<?= $type ?>',
personType: '<?= $personType ?>',
minLength: 2, // XXX probably should be set by config and default to 3
htmlId: '<?= $htmlId ?>'
htmlId: '<?= $htmlId ?>',
actionUrl: '<?= $constructedActionUrl ?>'
},
error: ''
}
Expand Down
18 changes: 16 additions & 2 deletions app/webroot/css/co-base.css
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ h1.loginMsg {
margin: 1em 0;
text-align: center;
}
body.in-iframe h1 {
font-size: 2em;
}
h2 {
font-size: 2em;
line-height: 2em;
Expand Down Expand Up @@ -637,7 +640,8 @@ ul.form-list li.alert-banner .co-alert {
display: flex;
justify-content: space-between;
margin: 1em 0 0.5em;
align-items: baseline;
align-items: flex-end;
flex-wrap: wrap;
}
#select-co.page-title-container {
margin: 0;
Expand Down Expand Up @@ -1008,8 +1012,13 @@ td.with-field-actions {
float: left;
padding-left: 1.5em;
margin-left: -1.5em;
}
.field-actions-menu {
margin-right: 0.75em;
}
.field-actions-menu.actions-expanded {
margin-right: 0;
}
.field-actions .dropdown-menu {
padding: 0;
font-size: 1em;
Expand Down Expand Up @@ -1596,12 +1605,17 @@ ul.form-list .cm-time-picker-vals li {
background-color: var(--cmg-color-highlight-018);
color: black;
}
.cm-people-picker-add {
/* PEOPLE PICKER */
#cm-people-picker {
display: flex;
flex-direction: column;
padding: 1em;
gap: 4px;
}
.group-member-to-add-name {
margin-right: 0.5em;
font-size: 1.4em;
}
/* Vue transitions */
.v-enter-active,
.v-leave-active {
Expand Down
31 changes: 18 additions & 13 deletions app/webroot/css/co-responsive.css
Original file line number Diff line number Diff line change
Expand Up @@ -296,14 +296,26 @@
margin: 10em 0 4em;
}
/* PEOPLE PICKER */
.cm-people-picker-add {
#cm-people-picker {
flex-direction: row;
align-items: center;
align-items: flex-end;
gap: 0.5em;
padding: 0;
}
.cm-people-picker-add .cm-people-picker-input {
width: 100px;
#cm-people-picker .cm-autocomplete {
width: 300px;
height: 30px;
}
#cm-people-picker #cmPersonPickerId-container {
position: relative;
display: flex;
align-items: center;
gap: 0.5em;
}
#cm-people-picker .co-loading-mini-container {
position: absolute;
right: 0.75em;
z-index: 1;
}
/* GENERAL */
.table-container {
Expand Down Expand Up @@ -393,7 +405,8 @@
}
.field-actions.top-links .actions-expanded .dropdown-menu {
position: static;
display: inline-block;
display: flex;
align-items: flex-end;
min-width: 0;
font-size: 0.9em;
border: none;
Expand Down Expand Up @@ -474,10 +487,6 @@
.config-menu {
column-count: 3;
}
/* PEOPLE PICKER */
.cm-people-picker-add .cm-people-picker-input {
width: 200px;
}
}

/* EXTRA LARGE */
Expand All @@ -496,10 +505,6 @@
.config-menu {
column-count: 4;
}
/* PEOPLE PICKER */
.cm-people-picker-add .cm-people-picker-input {
width: 300px;
}
.item-with-type {
grid-template-columns: 1fr 2fr;
}
Expand Down
Loading