add search filters to LibraryList and LibraryMap

This commit is contained in:
axolotle
2021-06-14 12:11:19 +02:00
parent 9c4018a615
commit a1f15457a0
5 changed files with 97 additions and 31 deletions
+18 -3
View File
@@ -1,8 +1,9 @@
<template>
<div class="library-list">
<div class="library-list-container">
<div v-for="(parents, char) in orderedTextsDepart" :key="char">
<div v-for="(parents, char) in filteredNodes" :key="char">
<h3>{{ char }}</h3>
<div class="library-list-nodes-group">
<node-view
v-for="parent in parents" :key="parent.id"
@@ -20,18 +21,32 @@
// FIXME let events bubble
import { mapGetters } from 'vuex'
import { searchInNode } from '@/store/utils'
import { NodeView } from '@/components/nodes'
export default {
name: 'CardList',
name: 'LibraryList',
components: {
NodeView
},
computed: {
...mapGetters(['orderedTextsDepart'])
...mapGetters(['orderedTextsDepart', 'search']),
filteredNodes () {
if (!this.orderedTextsDepart) return {}
const nodesGroups = {}
const search = this.search.toLowerCase()
Object.entries(this.orderedTextsDepart).forEach(([char, nodes]) => {
const filteredNodes = nodes.filter(node => searchInNode(search, node))
if (filteredNodes.length) {
nodesGroups[char] = filteredNodes
}
})
return nodesGroups
}
},
created () {
+17 -1
View File
@@ -2,13 +2,14 @@
<b-overlay :show="nodes === undefined" class="h-100">
<map-zoom id="library-map" :min-zoom="0.2" :max-zoom="2">
<foreignObject
v-for="(node, i) in nodes" :key="i"
v-for="(node, i) in filteredNodes" :key="i"
:style="`--x: ${node.x}px; --y: ${node.y}px; --r: ${node.rotate}deg;`"
>
<node-view
:node="node.data"
mode="card"
@open-node="onOpen(node.data)"
:hidden="node.hidden"
/>
</foreignObject>
</map-zoom>
@@ -18,7 +19,9 @@
<script>
import { randomUniform } from 'd3'
import { forceSimulation, forceCollide, forceManyBody } from 'd3-force'
import { mapGetters } from 'vuex'
import { searchInNode } from '@/store/utils'
import { MapZoom } from '@/components/layouts'
import { NodeView } from '@/components/nodes'
@@ -38,6 +41,19 @@ export default {
}
},
computed: {
...mapGetters(['search']),
filteredNodes () {
if (!this.nodes) return
const search = this.search.toLowerCase()
this.nodes.forEach(node => {
Object.assign(node, { hidden: !searchInNode(search, node.data) })
})
return this.nodes
}
},
methods: {
onOpen (node) {
// FIXME ALSO CHECK IF PARENT
+34 -25
View File
@@ -12,6 +12,7 @@
/>
</b-form-group>
<!-- LIST + MAP ONLY -->
<b-form-group
v-if="mode !== 'tree'"
:label="$t('options.filters.title')"
@@ -37,7 +38,20 @@
:disabled="true"
/>
</b-form-group>
<b-form-group
:label="$t('options.search.title')"
label-for="search-input"
>
<b-input-group append="search-icon">
<b-form-input
v-model="activeSearch" id="search-input" trim
/>
</b-input-group>
</b-form-group>
</b-form-group>
<!-- TREE ONLY -->
<b-form-group
v-else
label="Texte de départ:"
@@ -46,24 +60,11 @@
>
<b-form-select
id="text-depart-select"
v-model="nodeDepartId"
v-model="activeNodeId"
:options="nodesDepartsOptions"
class="border"
/>
</b-form-group>
<b-form-group
:label="$t('options.search.title')"
label-for="search-input"
>
<b-input-group append="search-icon">
<b-form-input
v-model="search" id="search-input" trim
:disabled="true"
/>
</b-input-group>
</b-form-group>
</div>
</template>
@@ -87,35 +88,43 @@ export default {
{ text: this.$t('options.display.choices.card-list'), value: 'list' }
],
selectedTags: [],
strangeness: 0,
textDepartId: undefined,
search: ''
strangeness: 0
}
},
computed: {
...mapGetters(['mode', 'nodebook', 'nodesDepartsOptions', 'tagsOptions']),
...mapGetters([
'mode',
'nodeDepartId',
'search',
'nodebook',
'nodesDepartsOptions',
'tagsOptions'
]),
show () {
return this.nodebook.length === 0
},
nodeDepartId: {
get () {
return this.$store.state.library.nodeDepartId
},
activeNodeId: {
get () { return this.nodeDepartId },
set (value) {
this.$store.dispatch('SET_NODE_DEPART_ID', value)
}
},
activeMode: {
get () {
return this.mode
},
get () { return this.mode },
set (value) {
this.$store.dispatch('UPDATE_QUERY_MODE', value)
}
},
activeSearch: {
get () { return this.search },
set (value) {
this.$store.commit('SET_SEARCH', value)
}
}
}
}
+9 -2
View File
@@ -20,7 +20,8 @@ export default {
nodeDepartId: undefined,
trees: {},
mode: undefined,
nodebook: undefined
nodebook: undefined,
search: ''
},
mutations: {
@@ -67,6 +68,10 @@ export default {
'SET_NODE_DEPART_ID' (state, id) {
state.nodeDepartId = id
},
'SET_SEARCH' (state, str) {
state.search = str
}
},
@@ -165,7 +170,9 @@ export default {
},
getters: {
mode: (state) => state.mode,
mode: state => state.mode,
nodeDepartId: state => state.nodeDepartId,
search: state => state.search,
nodebook: (state, getters, rootState) => {
if (!state.nodebook) return []
+19
View File
@@ -28,6 +28,8 @@ export const VARIANT_IDS = Object.fromEntries(
Object.entries(ID_VARIANTS).map(([key, value]) => [value, key])
)
export const SEARCH_KEYS = ['content', 'title', 'preTitle', 'authors']
export function parseNodesQueryParams ({ mode, nodes = [] }) {
let nodebook = typeof nodes === 'string' ? [nodes] : nodes
@@ -112,3 +114,20 @@ export function buildTree (treeData, nodesData) {
links
}
}
export function searchInNode (search, node) {
if (!search) return true
for (const key of SEARCH_KEYS) {
if (!node[key]) continue
let match = false
if (key === 'authors') {
match = node[key].some(author => author.name.toLowerCase().includes(search))
} else {
console.log(node[key].toLowerCase(), search)
match = node[key].toLowerCase().includes(search)
}
if (match) return true
}
return false
}