Usability improvements to advanced search panel. #321.

This commit is contained in:
mateuswetah 2022-02-22 16:25:04 -03:00
parent 88d6304069
commit cdf0d062ae
7 changed files with 163 additions and 276 deletions

View File

@ -1,5 +1,8 @@
<template>
<div class="tnc-advanced-search-container">
<div
tabindex="0"
class="tnc-advanced-search-container">
<h3>{{ $i18n.get('advanced_search') }}</h3>
<transition-group name="filter-item">
<b-field
v-for="(searchCriterion, index) in searchCriteria"
@ -130,10 +133,8 @@
<!-- Add button -->
<div class="add-link-advanced-search">
<a
@click="addSearchCriteria"
style="font-size: 0.75em;">
<span class="icon is-small">
<a @click="addSearchCriteria">
<span class="icon">
<i class="has-text-secondary tainacan-icon tainacan-icon-add"/>
</span>
{{ searchCriteria.length &lt;= 0 ?
@ -141,24 +142,36 @@
$i18n.get('add_another_search_criterion')
}}
</a>
<a
v-if="Object.keys(advancedSearchQuery.taxquery).length > 0 || Object.keys(advancedSearchQuery.metaquery).length > 0"
@click="clearSearch();">
<span class="icon">
<i class="has-text-secondary tainacan-icon tainacan-icon-remove"/>
</span>
{{ $i18n.get('label_remove_all_criteria') }}
</a>
</div>
<!-- Clear and search button -->
<div class="field is-grouped is-justify-content-flex-end">
<p
v-if="Object.keys(advancedSearchQuery.taxquery).length > 0 || Object.keys(advancedSearchQuery.metaquery).length > 0"
class="control">
<p class="control">
<button
@click="clearSearch(); performAdvancedSearch();"
class="button is-outlined">{{ $i18n.get('clear_search') }}</button>
@click="$emit('close')"
class="button is-outlined">
{{ $i18n.get('label_close_search') }}
</button>
</p>
<p class="control">
<button
@click="performAdvancedSearch()"
class="button is-success">{{ $i18n.get('apply') }}</button>
class="button is-secondary">
{{ $i18n.get('apply') }}
</button>
</p>
</div>
<b-loading
:is-full-page="false"
:active.sync="isLoadingMetadata" />
<section
v-if="!isLoadingMetadata && metadataAsArray && metadataAsArray.length <= 0"
class="field is-grouped-centered section">
@ -187,7 +200,6 @@
mixins: [ dateInter ],
props: {
isRepositoryLevel: false,
hasAdvancedSearchResults: false,
collectionId: ''
},
data() {
@ -333,40 +345,6 @@
this.addSearchCriteria();
}
},
removeCriterion(searchCriterion) {
let searchCriterionIndex = this.searchCriteria.findIndex((element) => element.index == searchCriterion.index && element.type == searchCriterion.type);
if (searchCriterionIndex >= 0) {
this.advancedSearchQuery[searchCriterion.type].splice(searchCriterion.index, 1);
this.searchCriteria.splice(searchCriterionIndex, 1);
for (let queryIndex = 0; queryIndex < this.advancedSearchQuery.metaquery.length; queryIndex++) {
let isCriterionIndexUpdated = false;
let expectedIndex = queryIndex;
while(!isCriterionIndexUpdated && expectedIndex < this.searchCriteria.length) {
if (this.searchCriteria[expectedIndex] && this.searchCriteria[expectedIndex].type == 'metaquery') {
this.$set(this.searchCriteria[expectedIndex], 'index', queryIndex);
isCriterionIndexUpdated = true;
} else {
expectedIndex++;
}
}
}
for (let queryIndex = 0; queryIndex < this.advancedSearchQuery.taxquery.length; queryIndex++) {
let isCriterionIndexUpdated = false;
let expectedIndex = queryIndex;
while(!isCriterionIndexUpdated && expectedIndex < this.searchCriteria.length) {
if (this.searchCriteria[expectedIndex] && this.searchCriteria[expectedIndex].type == 'taxquery') {
this.$set(this.searchCriteria[expectedIndex], 'index', queryIndex);
isCriterionIndexUpdated = true;
} else {
expectedIndex++;
}
}
}
}
},
addSearchCriteria() {
let aleatoryKey = Math.floor(Math.random() * (1000 - 2 + 1)) + 2;
@ -377,6 +355,50 @@
else
this.addSearchCriteria();
},
removeCriterion(searchCriterion) {
// First, check if this criterion row is defined
if (!searchCriterion.type) {
let searchCriterionIndex = this.searchCriteria.findIndex((element) => element.index == searchCriterion.index);
if (searchCriterionIndex >= 0)
this.searchCriteria.splice(searchCriterionIndex, 1);
// If it was defined, then we need to update advancedSearchQuery properly when removing
} else {
let searchCriterionIndex = this.searchCriteria.findIndex((element) => element.index == searchCriterion.index && element.type == searchCriterion.type);
if (searchCriterionIndex >= 0) {
this.advancedSearchQuery[searchCriterion.type].splice(searchCriterion.index, 1);
this.searchCriteria.splice(searchCriterionIndex, 1);
for (let queryIndex = 0; queryIndex < this.advancedSearchQuery.metaquery.length; queryIndex++) {
let isCriterionIndexUpdated = false;
let expectedIndex = queryIndex;
while(!isCriterionIndexUpdated && expectedIndex < this.searchCriteria.length) {
if (this.searchCriteria[expectedIndex] && this.searchCriteria[expectedIndex].type == 'metaquery') {
this.$set(this.searchCriteria[expectedIndex], 'index', queryIndex);
isCriterionIndexUpdated = true;
} else {
expectedIndex++;
}
}
}
for (let queryIndex = 0; queryIndex < this.advancedSearchQuery.taxquery.length; queryIndex++) {
let isCriterionIndexUpdated = false;
let expectedIndex = queryIndex;
while(!isCriterionIndexUpdated && expectedIndex < this.searchCriteria.length) {
if (this.searchCriteria[expectedIndex] && this.searchCriteria[expectedIndex].type == 'taxquery') {
this.$set(this.searchCriteria[expectedIndex], 'index', queryIndex);
isCriterionIndexUpdated = true;
} else {
expectedIndex++;
}
}
}
}
}
},
clearSearch() {
this.searchCriteria = [];
this.advancedSearchQuery = {
@ -522,22 +544,33 @@
#advanced-search-container {
width: calc(100% - (2 * var(--tainacan-one-column)));
margin: 0.5em var(--tainacan-one-column) 0.875em;
margin: 0 var(--tainacan-one-column) 0.875em;
background: var(--tainacan-input-background-color);
border: 1px solid var(--tainacan-input-border-color);
border-radius: 1px;
transition: height 0.2s ease;
}
.tnc-advanced-search-container {
padding: 1em;
padding-top: 3.5em;
position: relative;
padding: 1.25em;
.column {
padding: 0 0.5em 0.75em !important;
h3 {
font-size: 1em !important;
padding-top: 0 !important;
color: var(--tainacan-heading-color) !important;
margin-bottom: 1em !important;
}
.tainacan-form {
margin-bottom: 0.125em !important;
}
.column {
padding: 0;
}
.control {
font-size: 1em;
margin-bottom: 0px !important;
.select{
width: 100% !important;
select{
@ -546,8 +579,10 @@
}
}
.add-link-advanced-search {
padding-left: 8px !important;
.add-link-advanced-search a {
font-size: 0.8125em;
display: inline-flex;
align-items: center;
}
@media screen and (max-width: 768px) {

View File

@ -384,9 +384,6 @@ export default {
resp.request.then((res) => {
this.$emit( 'isLoadingItems', false);
this.$emit( 'hasFiltered', res.hasFiltered);
if (res.hasAdvancedSearchResults)
this.$emit('hasAdvancedSearchResults', res.hasAdvancedSearchResults);
})
.catch(() => {
this.$emit( 'isLoadingItems', false);

View File

@ -25,7 +25,6 @@ export const fetchItems = ({ rootGetters, dispatch, commit }, { collectionId, is
// Sets a flag to inform components that an empty sate is or not due to filtering
let hasFiltered = false;
let hasAdvancedSearchResults = false;
// We mark as filtered if there is a metaquery, taxquery or a postin
if (
@ -38,13 +37,8 @@ export const fetchItems = ({ rootGetters, dispatch, commit }, { collectionId, is
(postQueries.postin != undefined &&
postQueries.postin.length
)
) {
)
hasFiltered = true;
if (postQueries.advancedSearch)
hasAdvancedSearchResults = postQueries.advancedSearch;
}
// Admin default tab should load publish, private and draft statuses
if (!isOnTheme && !postQueries.status) {
@ -93,7 +87,6 @@ export const fetchItems = ({ rootGetters, dispatch, commit }, { collectionId, is
'itemsListTemplate': res.data.template,
'total': res.headers['x-wp-total'],
hasFiltered: hasFiltered,
hasAdvancedSearchResults: hasAdvancedSearchResults,
itemsPerPage: res.headers['x-wp-itemperpage']});
} else {
commit('setItems', items);
@ -102,7 +95,6 @@ export const fetchItems = ({ rootGetters, dispatch, commit }, { collectionId, is
'total': res.headers['x-wp-total'],
totalPages: res.headers['x-wp-totalpages'],
hasFiltered: hasFiltered,
hasAdvancedSearchResults: hasAdvancedSearchResults ,
itemsPerPage: res.headers['x-wp-itemperpage'] });
}
dispatch('search/setTotalItems', res.headers['x-wp-total'], { root: true } );

View File

@ -469,7 +469,7 @@
<advanced-search
:collection-id="collectionId"
:is-repository-level="isRepositoryLevel"
:has-advanced-search-results="hasAdvancedSearchResults" />
@close="openAdvancedSearch = false" />
</div>
</transition>
@ -519,8 +519,7 @@
<div
v-if="hasAnOpenAlert &&
isSortingByCustomMetadata &&
!showLoading &&
((openAdvancedSearch && hasAdvancedSearchResults) || !openAdvancedSearch)"
!showLoading"
class="metadata-alert">
<p class="text">
{{
@ -545,9 +544,7 @@
<!-- Admin View Modes-->
<items-list
v-if="!showLoading &&
totalItems > 0 &&
((openAdvancedSearch && hasAdvancedSearchResults) || !openAdvancedSearch)"
v-if="!showLoading && totalItems > 0"
:collection-id="collectionId"
:displayed-metadata="displayedMetadata"
:items="items"
@ -597,7 +594,7 @@
<div ref="items-pagination">
<pagination
:is-sorting-by-custom-metadata="isSortingByCustomMetadata"
v-if="totalItems > 0 && (hasAdvancedSearchResults || !openAdvancedSearch)"/>
v-if="totalItems > 0"/>
</div>
</div>
</div>
@ -642,7 +639,6 @@
localDisplayedMetadata: [],
registeredViewModes: tainacan_plugin.registered_view_modes,
openAdvancedSearch: false,
hasAdvancedSearchResults: false,
sortingMetadata: [],
isFiltersModalActive: false,
hasAnOpenModal: false,
@ -707,7 +703,6 @@
openAdvancedSearch(newValue) {
if (newValue == false){
this.$eventBusSearch.$emit('closeAdvancedSearch');
this.hasAdvancedSearchResults = false;
this.isFiltersModalActive = true;
} else {
this.isFiltersModalActive = false;
@ -751,10 +746,6 @@
this.hasFiltered = hasFiltered;
});
this.$eventBusSearch.$on('hasAdvancedSearchResults', hasAdvancedSearchResults => {
this.hasAdvancedSearchResults = hasAdvancedSearchResults;
});
this.$eventBusSearch.$on('hasToPrepareMetadataAndFilters', () => {
this.prepareMetadata();
});
@ -1288,7 +1279,6 @@
// $eventBusSearch
this.$eventBusSearch.$off('isLoadingItems');
this.$eventBusSearch.$off('hasFiltered');
this.$eventBusSearch.$off('hasAdvancedSearchResults');
this.$eventBusSearch.$off('hasToPrepareMetadataAndFilters');
}
}
@ -1308,58 +1298,6 @@
overflow-y: auto;
}
.advanced-search-criteria-title {
margin-bottom: 40px;
h1, h2 {
font-size: 1.25em;
font-weight: 500;
color: var(--tainacan-heading-color);
display: inline-block;
margin-bottom: 0;
}
.field.is-grouped {
margin-left: auto;
}
a.back-link{
font-weight: 500;
float: right;
margin-top: 5px;
}
hr{
margin: 3px 0px 4px 0px;
height: 2px;
background-color: var(--tainacan-secondary);
border: none;
}
}
.has-advanced-search-results-title {
margin-bottom: 40px;
margin: 0 var(--tainacan-one-column) 42px var(--tainacan-one-column);
h1, h2 {
font-size: 1.25em;
font-weight: 500;
color: var(--tainacan-heading-color);
display: inline-block;
margin-bottom: 0;
}
.field.is-grouped {
margin-left: auto;
}
a.back-link{
font-weight: 500;
float: right;
margin-top: 5px;
}
hr{
margin: 3px 0px 4px 0px;
height: 1px;
background-color: var(--tainacan-secondary);
}
}
.advanced-search-form-submit {
display: flex;
justify-content: flex-end;
@ -1499,10 +1437,6 @@
padding-right: 0;
max-width: 100% !important;
}
.advanced-search-toggle.is-closed {
position: relative;
right: 0px !important;
}
}
}
@ -1592,39 +1526,23 @@
margin-left: 12px;
white-space: nowrap;
position: absolute;
font-size: 0.75em;
right: 15px;
left: unset;
top: 100%;
transition: font-size 0.2s ease, right 0.3s ease, left 0.3s ease, top 0.4s ease;
.icon {
display: 0;
opacity: 0.0;
max-width: 0;
transition: opacity 0.2s ease, max-width 0.2s ease;
}
&.is-closed {
font-size: 0.75em;
right: 15px;
left: unset;
top: 100%;
.icon {
display: 0;
opacity: 0.0;
max-width: 0;
}
}
&.is-open {
font-size: 1em;
right: unset;
left: 15px;
top: 6.125em;
z-index: 9;
.icon {
display: inline;
opacity: 1.0;
max-width: 1.5em;
}
font-size: 0;
}
}
}
}

View File

@ -31,7 +31,7 @@
aria-controls="filters-modal"
:aria-expanded="isFiltersModalActive"
:class="hideHideFiltersButton ? 'is-hidden-tablet' : ''"
v-if="!showFiltersButtonInsideSearchControl && !hideFilters && !openAdvancedSearch && !(registeredViewModes[viewMode] != undefined && registeredViewModes[viewMode].full_screen)"
v-if="!showFiltersButtonInsideSearchControl && !hideFilters && !(registeredViewModes[viewMode] != undefined && registeredViewModes[viewMode].full_screen)"
id="filter-menu-compress-button"
:aria-label="!isFiltersModalActive ? $i18n.get('label_show_filters') : $i18n.get('label_hide_filters')"
@click="isFiltersModalActive = !isFiltersModalActive"
@ -75,8 +75,11 @@
v-if="!hideAdvancedSearch"
@click="openAdvancedSearch = !openAdvancedSearch; $eventBusSearch.clearAllFilters();"
style="font-size: 0.75em;"
class="has-text-secondary is-pulled-right">
class="advanced-search-toggle has-text-secondary is-pulled-right">
{{ $i18n.get('advanced_search') }}
<span class="icon">
<i class="tainacan-icon tainacan-icon-search" />
</span>
</a>
</div>
</div>
@ -347,34 +350,34 @@
</div>
<!-- SIDEBAR WITH FILTERS -->
<b-modal
v-if="!hideFilters"
role="region"
aria-labelledby="filters-label-landmark"
id="filters-modal"
ref="filters-modal"
:active.sync="isFiltersModalActive"
:width="736"
animation="slide-menu"
:auto-focus="filtersAsModal"
:trap-focus="filtersAsModal"
full-screen
:custom-class="'tainacan-modal tainacan-form filters-menu' + (filtersAsModal ? ' filters-menu-modal' : '')"
:can-cancel="hideHideFiltersButton || !filtersAsModal ? ['x', 'outside'] : ['x', 'escape', 'outside']"
:close-button-aria-label="$i18n.get('close')">
<filters-items-list
:is-loading-items="isLoadingItems"
:autofocus="filtersAsModal"
:tabindex="filtersAsModal ? -1 : 0"
:aria-modal="filtersAsModal"
:role="filtersAsModal ? 'dialog' : ''"
id="filters-items-list"
:taxonomy="taxonomy"
:collection-id="collectionId"
:is-repository-level="isRepositoryLevel"
:filters-as-modal="filtersAsModal"
:has-filtered="hasFiltered" />
</b-modal>
<template v-if="!hideFilters">
<b-modal
role="region"
aria-labelledby="filters-label-landmark"
id="filters-modal"
ref="filters-modal"
:active.sync="isFiltersModalActive"
:width="736"
:auto-focus="filtersAsModal"
:trap-focus="filtersAsModal"
full-screen
:custom-class="'tainacan-modal tainacan-form filters-menu' + (filtersAsModal ? ' filters-menu-modal' : '')"
:can-cancel="hideHideFiltersButton || !filtersAsModal ? ['x', 'outside'] : ['x', 'escape', 'outside']"
:close-button-aria-label="$i18n.get('close')">
<filters-items-list
:is-loading-items="isLoadingItems"
:autofocus="filtersAsModal"
:tabindex="filtersAsModal ? -1 : 0"
:aria-modal="filtersAsModal"
:role="filtersAsModal ? 'dialog' : ''"
id="filters-items-list"
:taxonomy="taxonomy"
:collection-id="collectionId"
:is-repository-level="isRepositoryLevel"
:filters-as-modal="filtersAsModal"
:has-filtered="hasFiltered" />
</b-modal>
</template>
<!-- ITEMS LIST AREA (ASIDE THE ASIDE) ------------------------- -->
<div
@ -391,7 +394,7 @@
<advanced-search
:is-repository-level="isRepositoryLevel"
:collection-id="collectionId"
:has-advanced-search-results="hasAdvancedSearchResults" />
@close="openAdvancedSearch = false" />
</div>
<!-- FILTERS TAG LIST-->
@ -444,8 +447,7 @@
<div
v-if="hasAnOpenAlert &&
isSortingByCustomMetadata &&
!showLoading &&
((openAdvancedSearch && hasAdvancedSearchResults) || !openAdvancedSearch)"
!showLoading"
class="metadata-alert">
<p class="text">
{{
@ -470,16 +472,14 @@
<!-- Theme View Modes -->
<div
v-if="((openAdvancedSearch && hasAdvancedSearchResults) || !openAdvancedSearch) &&
!showLoading &&
v-if="!showLoading &&
registeredViewModes[viewMode] != undefined &&
registeredViewModes[viewMode].type == 'template'"
v-html="itemsListTemplate"/>
<component
v-if="registeredViewModes[viewMode] != undefined &&
registeredViewModes[viewMode].type == 'component' &&
((openAdvancedSearch && hasAdvancedSearchResults) || !openAdvancedSearch)"
registeredViewModes[viewMode].type == 'component'"
:collection-id="collectionId"
:displayed-metadata="displayedMetadata"
:items="items"
@ -495,8 +495,7 @@
v-show="!hidePaginationArea"
:is-sorting-by-custom-metadata="isSortingByCustomMetadata"
v-if="totalItems > 0 &&
((registeredViewModes[viewMode] != undefined && registeredViewModes[viewMode].show_pagination)) &&
(hasAdvancedSearchResults || !openAdvancedSearch)"
((registeredViewModes[viewMode] != undefined && registeredViewModes[viewMode].show_pagination))"
:hide-items-per-page-button="hideItemsPerPageButton"
:hide-go-to-page-button="hideGoToPageButton"/>
@ -574,7 +573,6 @@
localDisplayedMetadata: [],
registeredViewModes: tainacan_plugin.registered_view_modes,
openAdvancedSearch: false,
hasAdvancedSearchResults: false,
sortingMetadata: [],
isFiltersModalActive: false,
hasAnOpenModal: false,
@ -640,7 +638,6 @@
openAdvancedSearch(newValue){
if (newValue == false){
this.$eventBusSearch.$emit('closeAdvancedSearch');
this.hasAdvancedSearchResults = false;
this.isFiltersModalActive = !this.startWithFiltersHidden;
} else {
this.isFiltersModalActive = false;
@ -698,9 +695,6 @@
});
if (!this.hideAdvancedSearch) {
this.$eventBusSearch.$on('hasAdvancedSearchResults', hasAdvancedSearchResults => {
this.hasAdvancedSearchResults = hasAdvancedSearchResults;
});
if (this.$route.query && this.$route.query.advancedSearch) {
this.openAdvancedSearch = this.$route.query.advancedSearch;
@ -1167,8 +1161,6 @@
// $eventBusSearch
this.$eventBusSearch.$off('isLoadingItems');
this.$eventBusSearch.$off('hasFiltered');
if (!this.hideAdvancedSearch)
this.$eventBusSearch.$off('hasAdvancedSearchResults');
this.$eventBusSearch.$off('hasToPrepareMetadataAndFilters');
},
@ -1212,58 +1204,6 @@
}
}
.advanced-search-criteria-title {
margin-bottom: 40px;
h1, h2 {
font-size: 1.25em !important;
font-weight: 500;
color: var(--tainacan-heading-color);
display: inline-block;
margin-bottom: 0;
}
.field.is-grouped {
margin-left: auto;
}
a.back-link{
font-weight: 500;
float: right;
margin-top: 5px;
}
hr{
margin: 3px 0px 4px 0px;
height: 2px;
background-color: var(--tainacan-secondary);
border: none;
}
}
.has-advanced-search-results-title {
margin-bottom: 40px;
margin: 0 var(--tainacan-one-column) 42px var(--tainacan-one-column);
h1, h2 {
font-size: 1.25em;
font-weight: 500;
color: var(--tainacan-heading-color);
display: inline-block;
margin-bottom: 0;
}
.field.is-grouped {
margin-left: auto;
}
a.back-link{
font-weight: 500;
float: right;
margin-top: 5px;
}
hr{
margin: 3px 0px 4px 0px;
height: 1px;
background-color: var(--tainacan-secondary);
}
}
.advanced-search-form-submit {
display: flex;
justify-content: flex-end;
@ -1274,16 +1214,6 @@
p { margin-left: 0.75em; }
}
.tnc-advanced-search-close {
padding-top: 47px;
padding-right: var(--tainacan-one-column);
padding-left: var(--tainacan-one-column);
.column {
padding: 0 0.3em 0.3em !important;
}
}
.page-container {
padding: 0;
}
@ -1476,15 +1406,27 @@
width: 100%;
margin: -2px 0 5px 0;
}
.is-pulled-right {
position: absolute;
right: 0;
top: 100%;
}
a {
a.advanced-search-toggle {
margin-left: 12px;
white-space: nowrap;
}
position: absolute;
font-size: 0.75em;
right: 15px;
left: unset;
top: 100%;
transition: font-size 0.2s ease, right 0.3s ease, left 0.3s ease, top 0.4s ease;
.icon {
display: 0;
opacity: 0.0;
max-width: 0;
transition: opacity 0.2s ease, max-width 0.2s ease;
}
&.is-open {
font-size: 0;
}
}
}
&#tainacanFiltersButton.is-filters-modal-active .gray-icon i::before {

View File

@ -49,6 +49,7 @@ export default {
// Buefy imports
@import "../../../../../node_modules/buefy/src/scss/utils/_all.scss";
@import "../../../../../node_modules/buefy/src/scss/components/_form.scss";
@import "../../../../../node_modules/buefy/src/scss/components/_datepicker.scss";
@import "../../../../../node_modules/buefy/src/scss/components/_checkbox.scss";
@import "../../../../../node_modules/buefy/src/scss/components/_radio.scss";

View File

@ -611,6 +611,8 @@ return apply_filters( 'tainacan-i18n', [
'label_limit_max_values' => __( 'Limit the amount of multiple values', 'tainacan'),
'label_items_selection' => __( 'Items selection', 'tainacan'),
'label_default_orderby' => __( 'Initial default sorting', 'tainacan' ),
'label_close_search' => __( 'Close search', 'tainacan' ),
'label_remove_all_criteria' => __( 'Remove all criteria', 'tainacan' ),
// Instructions. More complex sentences to guide user and placeholders
'instruction_delete_selected_collections' => __( 'Delete selected collections', 'tainacan' ),