Skip to content

Commit

Permalink
Merge pull request #2 from arlen/feature-rolesPickerImrpovements
Browse files Browse the repository at this point in the history
Roles picker enhancements
  • Loading branch information
Ioannis authored Feb 4, 2025
2 parents e225502 + 5da10e8 commit 76a52c0
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 75 deletions.
3 changes: 3 additions & 0 deletions app/resources/locales/en_US/menu.po
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ msgstr "Toggle menu collapse button"
msgid "options"
msgstr "Options"

msgid "person.canvas"
msgstr "Person Canvas"

msgid "registries"
msgstr "Available {0} Registries"

Expand Down
3 changes: 3 additions & 0 deletions app/resources/locales/en_US/operation.po
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ msgstr "show more"
msgid "autocomplete.people.desc"
msgstr "Begin typing to find a person (use at least {0} characters from a name, email address, or identifier)"

msgid "autocomplete.people.field.desc"
msgstr "Begin typing to find a person (use characters from a name, email address, or identifier)"

msgid "autocomplete.people.label"
msgstr "Search for a person"

Expand Down
8 changes: 8 additions & 0 deletions app/src/View/Helper/VueHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,25 @@ class VueHelper extends Helper {
'report.for',
'value.copied',
],
'menu' => [
'person.canvas'
],
'operation' => [
'add',
'add.member',
'add.owner',
'autocomplete.pager.show.more',
'autocomplete.people.desc',
'autocomplete.people.field.desc',
'autocomplete.people.label',
'autocomplete.people.placeholder',
'close',
'copy',
'copy.value',
'edit',
'primary',
'remove',
'view',
'visit.link',
],
'result' => [
Expand Down
5 changes: 1 addition & 4 deletions app/templates/element/form/infoDiv/autocomplete.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,4 @@
formParams: $formParams ?? []
);
?>
<div class="field-desc field-autocomplete-desc">
<span class="material-symbols-outlined">info</span>
<span><?= __d('operation','autocomplete.people.desc',['2']) ?></span>
</div>

5 changes: 4 additions & 1 deletion app/templates/element/peopleAutocomplete.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@
},
formParams: <?= json_encode($formParams ?? []) ?>,
},
error: ''
error: '',
core: {
webroot: '<?= $this->request->getAttribute('webroot') ?>'
}
}
},
components: {
Expand Down
10 changes: 10 additions & 0 deletions app/webroot/css/co-base.css
Original file line number Diff line number Diff line change
Expand Up @@ -1821,6 +1821,16 @@ ul.form-list .cm-time-picker-vals li {
text-decoration: underline;
background-color: var(--cmg-color-bg-002);
}
.cm-ac-input-group > div {
flex-grow: 1;
}
.cm-ac-link-to-person {
gap: 0.25em;
color: var(--cmg-color-link);
}
#main .cm-ac-link-to-person:hover {
text-decoration: none;
}
.item-with-type {
display: grid;
grid-template-columns: 1fr 1fr;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export default {
people: [],
rawData: [],
person: '',
personUrl: '',
identifierType: {},
emailType: {},
loading: false,
Expand Down Expand Up @@ -193,7 +194,7 @@ export default {
},
setPerson() {
if(['default', 'field'].includes(this.options.type)) {
this.options.inputProps.dataPersonid = this.person.value
this.options.inputProps.dataPersonid = 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;
Expand Down Expand Up @@ -248,7 +249,8 @@ export default {
if(this.options.inputValue != undefined
&& this.options.inputValue != ''
&& this.options.inputProps.name.endsWith('person_id')) {
this.person = `${this.options.formParams?.fullName} (ID: ${this.options.inputValue})`
this.person = `${this.options.formParams?.fullName} (ID: ${this.options.inputValue})`;
this.personUrl = `${this.core.webroot}people/edit/${this.options.inputValue}`;
}
},
computed: {
Expand Down Expand Up @@ -284,75 +286,86 @@ export default {
}
},
template: `
<label v-if="hasAutoCompleteLabel" class="mr-2" :for="this.options.htmlId">{{ this.autoCompleteLabel }}</label>
<MiniLoader :isLoading="loading" :classes="getMiniLoaderClasses"/>
<AutoComplete
v-model="person"
inputClass="cm-autocomplete"
:inputId="this.options.htmlId"
:inputProps="this.options.inputProps"
:placeholder="this.txt['operation.autocomplete.people.placeholder']"
panelClass="cm-autocomplete-panel"
optionLabel="label"
optionDisabled="isMember"
:minLength="this.options.minLength"
:delay="500"
loadingIcon=null
:suggestions="this.people"
forceSelection
@complete="searchPeople"
@show="calculateDisabled"
@keyup.arrow-down="onListNavigate"
@keyup.arrow-up="onListNavigate"
@item-select="setPerson">
<template #option="slotProps">
<div class="cm-ac-item">
<div class="cm-ac-item-primary">
<div class="cm-ac-name">
<!-- XXX The input field will be updated with the option.label value. Here we only need the full name -->
<span class="cm-ac-name-value" v-if="slotProps.option.isMember" v-html="slotProps.option.fullName"></span>
<span class="cm-ac-name-value" v-else v-html="this.highlightedquery(slotProps.option.fullName, query)"></span>
<span class="mr-1 badge bg-success" v-if="slotProps.option.isMember">{{ this.txt['controller.GroupMembers'] }}</span>
<label v-if="hasAutoCompleteLabel" class="mr-2" :for="this.options.htmlId">{{ this.autoCompleteLabel }}</label>
<MiniLoader :isLoading="loading" :classes="getMiniLoaderClasses"/>
<div class="cm-ac-input-group input-group">
<AutoComplete
v-model="person"
inputClass="cm-autocomplete"
:inputId="this.options.htmlId"
:inputProps="this.options.inputProps"
:placeholder="this.txt['operation.autocomplete.people.placeholder']"
panelClass="cm-autocomplete-panel"
optionLabel="label"
optionDisabled="isMember"
:minLength="this.options.minLength"
:delay="500"
loadingIcon=null
:suggestions="this.people"
forceSelection
@complete="searchPeople"
@show="calculateDisabled"
@keyup.arrow-down="onListNavigate"
@keyup.arrow-up="onListNavigate"
@item-select="setPerson">
<template #option="slotProps">
<div class="cm-ac-item">
<div class="cm-ac-item-primary">
<div class="cm-ac-name">
<!-- XXX The input field will be updated with the option.label value. Here we only need the full name -->
<span class="cm-ac-name-value" v-if="slotProps.option.isMember" v-html="slotProps.option.fullName"></span>
<span class="cm-ac-name-value" v-else v-html="this.highlightedquery(slotProps.option.fullName, query)"></span>
<span class="mr-1 badge bg-success" v-if="slotProps.option.isMember">{{ this.txt['controller.GroupMembers'] }}</span>
</div>
<div class="cm-ac-item-id">
ID: {{ slotProps.option.itemId }}
</div>
</div>
<div class="cm-ac-subitems">
<div class="cm-ac-subitem cm-ac-email" v-if="slotProps.option.email">
<span class="cm-ac-label" v-if="slotProps.option.emailLabel">{{ slotProps.option.emailLabel }}</span>
<span class="cm-ac-value">
<ItemWithType
v-for="item in slotProps.option.email"
:item="item"
kind="email"
:query="query"
:highlightedquery="highlightedquery"
:isMember="slotProps.option.isMember"
/>
</span>
</div>
<div class="cm-ac-subitem cm-ac-id" v-if="slotProps.option.identifier">
<span class="cm-ac-label" v-if="slotProps.option.identifierLabel">{{ slotProps.option.identifierLabel }}</span>
<span class="cm-ac-value">
<ItemWithType
v-for="item in slotProps.option.identifier"
:query="query"
:item="item"
kind="identifier"
:highlightedquery="highlightedquery"
:isMember="slotProps.option.isMember"
/>
</span>
</div>
</div>
</div>
<div class="cm-ac-item-id">
ID: {{ slotProps.option.itemId }}
</template>
<template #footer="slotProps" v-if="hasMorePages">
<div class="cm-ac-pager">
<a href="#" @click="this.fetchMorePeople()">{{ this.txt['operation.autocomplete.pager.show.more'] }}</a>
</div>
</div>
<div class="cm-ac-subitems">
<div class="cm-ac-subitem cm-ac-email" v-if="slotProps.option.email">
<span class="cm-ac-label" v-if="slotProps.option.emailLabel">{{ slotProps.option.emailLabel }}</span>
<span class="cm-ac-value">
<ItemWithType
v-for="item in slotProps.option.email"
:item="item"
kind="email"
:query="query"
:highlightedquery="highlightedquery"
:isMember="slotProps.option.isMember"
/>
</span>
</div>
<div class="cm-ac-subitem cm-ac-id" v-if="slotProps.option.identifier">
<span class="cm-ac-label" v-if="slotProps.option.identifierLabel">{{ slotProps.option.identifierLabel }}</span>
<span class="cm-ac-value">
<ItemWithType
v-for="item in slotProps.option.identifier"
:query="query"
:item="item"
kind="identifier"
:highlightedquery="highlightedquery"
:isMember="slotProps.option.isMember"
/>
</span>
</div>
</div>
</div>
</template>
<template #footer="slotProps" v-if="hasMorePages">
<div class="cm-ac-pager">
<a href="#" @click="this.fetchMorePeople()">{{ this.txt['operation.autocomplete.pager.show.more'] }}</a>
</div>
</template>
</AutoComplete>
</template>
</AutoComplete>
<a v-if="this.person" :href="this.personUrl" class="input-group-text cm-ac-link-to-person">
<span class="material-symbols">person_check</span>
<span class="cm-ac-link-to-person-text">{{ this.txt['menu.person.canvas'] }}</span>
</a>
</div>
<div v-if="this.options.type == 'field'" class="field-desc field-autocomplete-desc">
<span class="material-symbols-outlined">info</span>
<span>{{ this.txt['operation.autocomplete.people.field.desc'] }}</span>
</div>
</div>
`
}

0 comments on commit 76a52c0

Please sign in to comment.