Skip to content
Snippets Groups Projects
Commit d2269644 authored by ml bonhomme's avatar ml bonhomme :bee: Committed by Erwan Rouchet
Browse files

Allow sorting facets by name or occurrences

parent 3d413e39
No related branches found
No related tags found
1 merge request!1401Allow sorting facets by name or occurrences
<template>
<div
class="card"
v-if="sortedItems.length"
>
<div class="card-header">
<div class="card-header-title is-capitalized">{{ name.replace('_', ' ') }}</div>
<div
v-if="sortedItems.length > 1"
class="facet-sort has-text-right"
v-on:click="nameSort = !nameSort"
>
<a>{{ sortingOption }}</a>
</div>
</div>
<div class="card-content">
<div
v-for="([value, count]) in sortedItems"
:key="value"
>
<input
type="checkbox"
:disabled="loading || null"
v-on:change="updateChecked(value, $event.target.checked)"
:checked="modelValue === value"
/> <label :for="value" :title="value">{{ truncateSelect(value) }} ({{ count }})</label>
<!-- The input and label tags must be on the same line for the space between checkbox and label to show -->
</div>
</div>
</div>
</template>
<script>
import { truncateMixin } from '@/mixins'
import { orderBy } from 'lodash'
export default {
emits: ['update:modelValue'],
mixins: [
truncateMixin
],
props: {
name: {
type: String,
required: true
},
values: {
type: Object,
required: true
},
modelValue: {
type: String,
required: true
}
},
data: () => ({
nameSort: true,
loading: false,
checkedFacets: []
}),
computed: {
sortingOption () {
if (this.nameSort) return 'Sort by occurrences'
return 'Sort by name'
},
sortedItems () {
if (this.modelValue) return [[this.modelValue, this.values[this.modelValue]]]
else {
const arrayed = Object.entries(this.values).filter(item => item[1] > 0)
if (this.nameSort) return orderBy(arrayed, 0, 'asc')
else return orderBy(arrayed, [1, 0], ['desc', 'asc'])
}
}
},
methods: {
updateChecked (facet, value) {
if (value) this.$emit('update:modelValue', facet)
else this.$emit('update:modelValue', '')
}
}
}
</script>
<style scoped>
.facet-sort {
padding-top: 0.75em;
padding-bottom: 0.75em;
padding-right: 1em;
}
</style>
......@@ -57,35 +57,19 @@
</div>
</div>
<!-- Facet form -->
<div
v-for="(facet, facetName) in facets"
:key="facetName"
class="card"
>
<div class="card-header">
<div class="card-header-title is-capitalized">{{ facetName.replace('_', ' ') }}</div>
</div>
<div class="card-content">
<div
v-for="(values, key) in facet"
:key="key"
>
<input
type="checkbox"
:id="key"
v-model="values.checked"
v-on:change="submit"
:disabled="loading || null"
/> <label :for="key" :title="key">{{ truncateSelect(key) }} ({{ values.value }})</label>
<!-- The input and label tags must be on the same line for the space between checkbox and label to show -->
</div>
</div>
</div>
<Facet
v-for="(values, name) in allFacets"
:key="name"
:name="name"
:values="allFacets[name]"
v-on:change="submit"
v-model="checkedFacets[name]"
/>
</form>
</template>
<script>
import { isEmpty } from 'lodash'
import { cloneDeep } from 'lodash'
import { UUID_REGEX } from '@/config'
import { SEARCH_HELP } from '@/help'
......@@ -93,6 +77,7 @@ import { ensureArray } from '@/helpers'
import { truncateMixin } from '@/mixins'
import HelpModal from '@/components/HelpModal.vue'
import Facet from './Facet'
export default {
emits: ['update:params'],
......@@ -100,7 +85,8 @@ export default {
truncateMixin
],
components: {
HelpModal
HelpModal,
Facet
},
props: {
corpusId: {
......@@ -125,28 +111,17 @@ export default {
currentTerms: '',
allSources: ['element', 'transcription', 'metadata', 'entity'],
sources: ['element', 'transcription', 'metadata', 'entity'],
facets: {},
sort: 'relevance',
SEARCH_HELP
SEARCH_HELP,
checkedFacets: {}
}),
methods: {
reset () {
this.currentTerms = ''
this.sources = this.allSources
this.facets = {}
this.checkedFacets = {}
this.submit()
},
getOldValue (oldFacets, facetName, facetItem) {
return (
(!isEmpty(oldFacets) &&
!isEmpty(oldFacets[facetName]) &&
!isEmpty(oldFacets[facetName][facetItem]) &&
oldFacets[facetName][facetItem].checked) ||
(!isEmpty(this.params) &&
!isEmpty(this.params[facetName]) &&
this.params[facetName] === facetItem)
)
},
updateSources (event) {
const element = event.srcElement
const index = this.sources.indexOf(element.id)
......@@ -154,20 +129,13 @@ export default {
else this.sources.push(element.id)
this.submit()
},
updateFacets () {
// Keep the old checked facets
const oldFacets = this.facets
this.facets = {}
for (const facetName in this.allFacets) {
const facetObject = this.allFacets[facetName]
const filter = {}
for (const facetItem in facetObject) {
// Remove facet without results
if (facetObject[facetItem] > 0) filter[facetItem] = { value: facetObject[facetItem], checked: this.getOldValue(oldFacets, facetName, facetItem) }
}
// Remove facet without values
if (!isEmpty(filter)) this.facets[facetName] = filter
updateCheckedFacets () {
const facets = cloneDeep(this.checkedFacets)
for (const item in this.allFacets) {
if (!(item in facets)) facets[item] = ''
if (this.params?.[item]) facets[item] = this.params[item]
}
this.checkedFacets = facets
},
parseParams () {
// Parse URL params
......@@ -175,7 +143,7 @@ export default {
// When there is only one source in the URL, the parameter might be a single string and not an array
if (this.params.sources) this.sources = ensureArray(this.params.sources)
this.updateFacets()
this.updateCheckedFacets()
},
/**
* Submit the currently selected query, but remove the `page` parameter from the paginator to restart at the beginning.
......@@ -186,21 +154,12 @@ export default {
},
computed: {
parsedQuery () {
// Retrieve checked facets
const checkedFacets = {}
for (const facetName in this.facets) {
const facetObject = this.facets[facetName]
for (const facetItem in facetObject) {
if (facetObject[facetItem].checked) checkedFacets[facetName] = facetItem
}
}
return {
query: this.currentTerms.trim() || '*',
only_facets: this.isEmpty.toString(),
sources: [...this.sources],
sort: this.sort,
...checkedFacets
...this.checkedFacets
}
},
isEmpty () {
......@@ -209,7 +168,7 @@ export default {
}
},
watch: {
allFacets: 'updateFacets',
allFacets: 'updateCheckedFacets',
// Search again if we switch to another project, after resetting all the parameters.
corpusId: 'reset',
// Parse from URL again if the URL params change
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment