Creates select filter for taxonomies and updates max options feature for existing select filter. #912.
This commit is contained in:
parent
4e360985ee
commit
7e774a24ac
|
@ -107,7 +107,7 @@ class Filters extends Repository {
|
|||
'map' => 'meta',
|
||||
'title' => __( 'Max of options', 'tainacan' ),
|
||||
'type' => ['integer', 'string'],
|
||||
'description' => __( 'The max number of options to be showed in filter sidebar.', 'tainacan' ),
|
||||
'description' => __( 'The maximum number of options to be loaded by default on the filter.', 'tainacan' ),
|
||||
'validation' => '',
|
||||
'default' => 4
|
||||
],
|
||||
|
|
|
@ -111,7 +111,7 @@ function tainacan_autoload($class_name) {
|
|||
}
|
||||
|
||||
if( in_array('Metadata_Types', $class_path) || in_array('Filter_Types', $class_path) ){
|
||||
$exceptions = ['taxonomytaginput','taxonomycheckbox'];
|
||||
$exceptions = ['taxonomytaginput','taxonomycheckbox','taxonomyselectbox'];
|
||||
if( in_array( strtolower( $class_name ), $exceptions) ){
|
||||
$dir.= 'taxonomy/';
|
||||
}else{
|
||||
|
|
|
@ -179,7 +179,8 @@
|
|||
v-model="form.max_options"
|
||||
name="max_options"
|
||||
type="number"
|
||||
step="1" />
|
||||
step="1"
|
||||
:max="maxOptionsLimit" />
|
||||
<button
|
||||
class="button is-white is-pulled-right"
|
||||
@click.prevent="showEditMaxOptions = false">
|
||||
|
@ -327,7 +328,8 @@ export default {
|
|||
closedByForm: false,
|
||||
showEditMaxOptions: false,
|
||||
entityName: 'filter',
|
||||
isLoading: false
|
||||
isLoading: false,
|
||||
maxOptionsLimit: tainacan_plugin.api_max_items_per_page && !isNaN(tainacan_plugin.api_max_items_per_page) ? Number(tainacan_plugin.api_max_items_per_page) : 96
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
|
|
@ -42,6 +42,7 @@ class Filter_Type_Helper {
|
|||
$this->Tainacan_Filters->register_filter_type('Tainacan\Filter_Types\Numeric_Interval');
|
||||
$this->Tainacan_Filters->register_filter_type('Tainacan\Filter_Types\TaxonomyTaginput');
|
||||
$this->Tainacan_Filters->register_filter_type('Tainacan\Filter_Types\TaxonomyCheckbox');
|
||||
$this->Tainacan_Filters->register_filter_type('Tainacan\Filter_Types\TaxonomySelectbox');
|
||||
$this->Tainacan_Filters->register_filter_type('Tainacan\Filter_Types\Numeric_List_Interval');
|
||||
$this->Tainacan_Filters->register_filter_type('Tainacan\Filter_Types\Numerics_Intersection');
|
||||
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
<template>
|
||||
<div
|
||||
:class="{ 'skeleton': isLoadingOptions }"
|
||||
class="block">
|
||||
<div class="block">
|
||||
<b-select
|
||||
v-if="!isLoadingOptions"
|
||||
:loading="isLoadingOptions"
|
||||
:disabled="!isLoadingOptions && options.length <= 0"
|
||||
:model-value="selected"
|
||||
:aria-labelledby="'filter-label-id-' + filter.id"
|
||||
:placeholder="filter.placeholder ? filter.placeholder : $i18n.get('label_selectbox_init')"
|
||||
expanded
|
||||
@update:model-value="($event) => { resetPage(); onSelect($event) }">
|
||||
<option value="">
|
||||
{{ $i18n.get('label_selectbox_init') }}...
|
||||
{{ filter.placeholder ? filter.placeholder : $i18n.get('label_selectbox_init') }}
|
||||
</option>
|
||||
<option
|
||||
v-for="(option, index) in options"
|
||||
:key="index"
|
||||
:label="option.label"
|
||||
:label="option.label + ( option.total_items ? (' (' + option.total_items + ')') : '' )"
|
||||
:value="option.value">
|
||||
{{ option.label }}
|
||||
<span
|
||||
|
@ -76,7 +75,9 @@
|
|||
promise = this.getValuesPlainText({
|
||||
metadatumId: this.metadatumId,
|
||||
search: null,
|
||||
isRepositoryLevel: this.isRepositoryLevel
|
||||
isRepositoryLevel: this.isRepositoryLevel,
|
||||
number: this.filter.max_options,
|
||||
offset: 0
|
||||
});
|
||||
promise.request
|
||||
.then((res) => {
|
||||
|
|
|
@ -12,7 +12,7 @@ class Selectbox extends Filter_Type {
|
|||
$this->set_name( __('Select Box', 'tainacan') );
|
||||
$this->set_supported_types(['string', 'long_string']);
|
||||
$this->set_component('tainacan-filter-selectbox');
|
||||
$this->set_use_max_options(false);
|
||||
$this->set_use_max_options(true);
|
||||
$this->set_preview_template('
|
||||
<div>
|
||||
<div class="control is-expanded">
|
||||
|
|
|
@ -138,6 +138,7 @@
|
|||
TainacanFilterTaginput: defineAsyncComponent(() => import('./taginput/TainacanFilterTaginput.vue')),
|
||||
TainacanFilterTaxonomyCheckbox: defineAsyncComponent(() => import('./taxonomy/TainacanFilterCheckbox.vue')),
|
||||
TainacanFilterTaxonomyTaginput: defineAsyncComponent(() => import('./taxonomy/TainacanFilterTaginput.vue')),
|
||||
TainacanFilterTaxonomySelectbox: defineAsyncComponent(() => import('./taxonomy/TainacanFilterSelectbox.vue')),
|
||||
TainacanFilterDateInterval: defineAsyncComponent(() => import('./date-interval/TainacanFilterDateInterval.vue')),
|
||||
TainacanFilterDatesIntersection: defineAsyncComponent(() => import('./dates-intersection/TainacanFilterDatesIntersection.vue')),
|
||||
TainacanFilterNumericInterval: defineAsyncComponent(() => import('./numeric-interval/TainacanFilterNumericInterval.vue')),
|
||||
|
|
|
@ -0,0 +1,210 @@
|
|||
<template>
|
||||
<div class="block">
|
||||
<b-select
|
||||
:loading="isLoadingOptions"
|
||||
:disabled="!isLoadingOptions && options.length <= 0"
|
||||
:model-value="selected"
|
||||
:aria-labelledby="'filter-label-id-' + filter.id"
|
||||
:placeholder="filter.placeholder ? filter.placeholder : $i18n.get('label_selectbox_init')"
|
||||
expanded
|
||||
@update:model-value="($event) => { resetPage(); onSelect($event) }">
|
||||
<option value="">
|
||||
{{ filter.placeholder ? filter.placeholder : $i18n.get('label_selectbox_init') }}
|
||||
</option>
|
||||
<option
|
||||
v-for="(option, index) in options"
|
||||
:key="index"
|
||||
:label="option.label + ( option.total_items ? (' (' + option.total_items + ')') : '' )"
|
||||
:value="option.value">
|
||||
<span
|
||||
v-if="option.total_items != undefined"
|
||||
class="has-text-gray">{{ "(" + option.total_items + ")" }}</span>
|
||||
</option>
|
||||
</b-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import qs from 'qs';
|
||||
import { tainacanApi, CancelToken, isCancel } from '../../../js/axios';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { filterTypeMixin } from '../../../js/filter-types-mixin';
|
||||
|
||||
export default {
|
||||
mixins: [ filterTypeMixin ],
|
||||
emits: [
|
||||
'input',
|
||||
'update-parent-collapse'
|
||||
],
|
||||
data(){
|
||||
return {
|
||||
isLoadingOptions: false,
|
||||
getOptionsValuesCancel: undefined,
|
||||
selected: '',
|
||||
options: [],
|
||||
taxonomy: '',
|
||||
taxonomyId: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('search', {
|
||||
'facetsFromItemSearch': 'getFacets'
|
||||
}),
|
||||
},
|
||||
watch: {
|
||||
facetsFromItemSearch: {
|
||||
handler() {
|
||||
if (this.isUsingElasticSearch)
|
||||
this.loadOptions();
|
||||
},
|
||||
immediate: true,
|
||||
deep:true
|
||||
},
|
||||
isLoadingItems: {
|
||||
handler() {
|
||||
if ( this.isUsingElasticSearch )
|
||||
this.isLoadingOptions = this.isLoadingItems;
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
'query': {
|
||||
handler() {
|
||||
this.updateSelectedValues();
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (!this.isUsingElasticSearch)
|
||||
this.loadOptions();
|
||||
},
|
||||
created() {
|
||||
if (this.filter.metadatum &&
|
||||
this.filter.metadatum.metadata_type_object &&
|
||||
this.filter.metadatum.metadata_type_object.options &&
|
||||
this.filter.metadatum.metadata_type_object.options.taxonomy &&
|
||||
this.filter.metadatum.metadata_type_object.options.taxonomy_id
|
||||
) {
|
||||
this.taxonomyId = this.filter.metadatum.metadata_type_object.options.taxonomy_id;
|
||||
this.taxonomy = this.filter.metadatum.metadata_type_object.options.taxonomy;
|
||||
}
|
||||
|
||||
this.$eventBusSearchEmitter.on('hasToReloadFacets', this.reloadOptions);
|
||||
},
|
||||
beforeUnmount() {
|
||||
|
||||
// Cancels previous Request
|
||||
if (this.getOptionsValuesCancel != undefined)
|
||||
this.getOptionsValuesCancel.cancel('Facet search Canceled.');
|
||||
|
||||
this.$eventBusSearchEmitter.off('hasToReloadFacets', this.reloadOptions);
|
||||
},
|
||||
methods: {
|
||||
reloadOptions(shouldReload) {
|
||||
if ( !this.isUsingElasticSearch && shouldReload )
|
||||
this.loadOptions();
|
||||
},
|
||||
loadOptions() {
|
||||
if (!this.isUsingElasticSearch) {
|
||||
let promise = null;
|
||||
const source = CancelToken.source();
|
||||
|
||||
// Cancels previous Request
|
||||
if (this.getOptionsValuesCancel != undefined)
|
||||
this.getOptionsValuesCancel.cancel('Facet search Canceled.');
|
||||
|
||||
this.isLoadingOptions = true;
|
||||
let query_items = { 'current_query': this.query };
|
||||
|
||||
let route = '';
|
||||
|
||||
if (this.isRepositoryLevel)
|
||||
route = `/facets/${this.metadatumId}?getSelected=1&order=asc&parent=0&number=${this.filter.max_options}&` + qs.stringify(query_items);
|
||||
else {
|
||||
if (this.filter.collection_id == 'default' && this.currentCollectionId)
|
||||
route = `/collection/${this.currentCollectionId}/facets/${this.metadatumId}?getSelected=1&order=asc&number=${this.filter.max_options}&` + qs.stringify(query_items);
|
||||
else
|
||||
route = `/collection/${this.filter.collection_id}/facets/${this.metadatumId}?getSelected=1&order=asc&number=${this.filter.max_options}&` + qs.stringify(query_items);
|
||||
}
|
||||
|
||||
this.options = [];
|
||||
|
||||
promise = new Object({
|
||||
request:
|
||||
new Promise((resolve, reject) => {
|
||||
tainacanApi.get(route, { cancelToken: source.token})
|
||||
.then( res => {
|
||||
resolve(res)
|
||||
})
|
||||
.catch(error => {
|
||||
reject(error)
|
||||
});
|
||||
}),
|
||||
source: source
|
||||
});
|
||||
promise.request
|
||||
.then((res) => {
|
||||
this.isLoadingOptions = false;
|
||||
this.prepareOptionsForTaxonomy(res.data.values ? res.data.values : res.data);
|
||||
|
||||
if (res && res.data && res.data.values)
|
||||
this.$emit('update-parent-collapse', res.data.values.length > 0 );
|
||||
})
|
||||
.catch( error => {
|
||||
if (isCancel(error)) {
|
||||
this.$console.log('Request canceled: ' + error.message);
|
||||
} else {
|
||||
this.$console.log('Error on facets request: ', error);
|
||||
this.isLoadingOptions = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Search Request Token for cancelling
|
||||
this.getOptionsValuesCancel = promise.source;
|
||||
|
||||
} else {
|
||||
for (const facet in this.facetsFromItemSearch) {
|
||||
if (facet == this.filter.id) {
|
||||
if (Array.isArray(this.facetsFromItemSearch[facet])) {
|
||||
this.prepareOptionsForTaxonomy(this.facetsFromItemSearch[facet]);
|
||||
this.$emit('update-parent-collapse', this.facetsFromItemSearch[facet].length > 0 );
|
||||
} else {
|
||||
this.prepareOptionsForTaxonomy(Object.values(this.facetsFromItemSearch[facet]));
|
||||
this.$emit('update-parent-collapse', Object.values(this.facetsFromItemSearch[facet]).length > 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
updateSelectedValues() {
|
||||
|
||||
if ( !this.query || !this.query.taxquery || !Array.isArray( this.query.taxquery ) )
|
||||
return false;
|
||||
|
||||
// Cleared either way, we might be coming from a situation where all the filters were removed.
|
||||
this.selected = '';
|
||||
|
||||
const index = this.query.taxquery.findIndex(newMetadatum => newMetadatum.taxonomy == this.taxonomy);
|
||||
if (index >= 0) {
|
||||
const metadata = this.query.taxquery[ index ];
|
||||
if (this.selected != metadata.terms)
|
||||
this.selected = metadata.terms;
|
||||
}
|
||||
},
|
||||
onSelect(selection) {
|
||||
this.$emit('input', {
|
||||
filter: 'selectbox',
|
||||
taxonomy: this.taxonomy,
|
||||
metadatum_id: this.metadatumId,
|
||||
collection_id: this.collectionId,
|
||||
terms: selection
|
||||
});
|
||||
},
|
||||
prepareOptionsForTaxonomy(items) {
|
||||
this.options = [];
|
||||
this.options = items.slice(); // copy array.
|
||||
this.updateSelectedValues();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
namespace Tainacan\Filter_Types;
|
||||
|
||||
defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
|
||||
|
||||
/**
|
||||
* Class TaxonomySelectbox
|
||||
*/
|
||||
class TaxonomySelectbox extends Filter_Type {
|
||||
|
||||
function __construct(){
|
||||
$this->set_name( __('Selectbox', 'tainacan') );
|
||||
$this->set_supported_types(['term']);
|
||||
$this->set_component('tainacan-filter-taxonomy-selectbox');
|
||||
$this->set_preview_template('
|
||||
<div>
|
||||
<div class="control is-expanded">
|
||||
<span class="select is-fullwidth">
|
||||
<select>
|
||||
<option value="someValue">' . __('Select here...') . '</option>
|
||||
</select>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
');
|
||||
}
|
||||
}
|
|
@ -258,6 +258,7 @@
|
|||
});
|
||||
}
|
||||
|
||||
// Presets second tab as active to display selected items
|
||||
if ( this.itemMetadatum.value.length > 0 && this.itemMetadatum.metadatum.multiple != 'yes' )
|
||||
this.activeTab = 1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue