Skip to content

Commit

Permalink
Fix: filter classes on a search query (#90)
Browse files Browse the repository at this point in the history
The classes select menu did not filter when queried, and would did not
update when the mine was changed. This commit fixes this by indexing
the available classes on first render and each time the mine changes.

Closes: #89

Squashed commits:
Change available classes when the mine changes
Rebuild search index when the mine changes
Reset the query when the popup closes
  • Loading branch information
JM-Mendez committed Jul 15, 2020
1 parent dc624f3 commit 14dd912
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 55 deletions.
41 changes: 41 additions & 0 deletions src/buildSearchIndex.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import FlexSearch from 'flexsearch'

import { indexWorker } from './searchIndex'

export const buildSearchIndex = async ({ docId, docField, values }) => {
// The configuration *must* be the same for import and export
const indexConfig = {
encode: 'advanced',
tokenize: 'reverse',
suggest: true,
cache: true,
doc: {
id: docId,
field: docField,
},
}

const exportConfig = {
index: true,
doc: true,
}

// @ts-ignore
const index = new FlexSearch(indexConfig)

if (typeof window !== 'undefined' && window.Worker) {
const serializedIndex = await indexWorker.index({
values,
indexConfig,
exportConfig,
})

// @ts-ignore
index.import(serializedIndex, exportConfig)
} else {
// @ts-ignore
index.add(values)
}

return index
}
38 changes: 26 additions & 12 deletions src/components/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ const supervisorMachine = Machine(
classView: 'Gene',
intermines: [],
modelClasses: [],
classSearchIndex: null,
selectedMine: {
rootUrl: 'https://www.humanmine.org/humanmine',
name: 'HumanMine',
Expand All @@ -44,7 +43,7 @@ const supervisorMachine = Machine(
},
idle: {
on: {
[CHANGE_MINE]: { actions: 'changeMine' },
[CHANGE_MINE]: { target: 'loading', actions: 'changeMine' },
[CHANGE_CLASS]: { actions: 'changeClass' },
},
},
Expand All @@ -63,22 +62,37 @@ const supervisorMachine = Machine(
// @ts-ignore
setIntermines: assign((ctx, { data }) => {
ctx.intermines = data.intermines
ctx.modelClasses = data.modelClasses.sort()
ctx.modelClasses = data.modelClasses
.sort()
.map((cl) => ({ displayName: cl.displayName, name: cl.name }))
}),
},
services: {
fetchMinesAndClasses: async (ctx, event) => {
const [instancesResult, classesResult] = await Promise.all([
fetchInstances(),
fetchClasses(ctx.selectedMine.rootUrl),
])
let instances
let modelClasses

if (ctx.intermines.length === 0) {
const [instancesResult, classesResult] = await Promise.all([
fetchInstances(),
fetchClasses(ctx.selectedMine.rootUrl),
])

instances = instancesResult
modelClasses = classesResult
} else {
modelClasses = await fetchClasses(ctx.selectedMine.rootUrl)
}

return {
modelClasses: Object.entries(classesResult.classes).map(([_key, value]) => value),
intermines: instancesResult.data.instances.map((mine) => ({
name: mine.name,
rootUrl: mine.url,
})),
modelClasses: Object.entries(modelClasses.classes).map(([_key, value]) => value),
intermines:
ctx.intermines.length > 0
? ctx.intermines
: instances.data.instances.map((mine) => ({
name: mine.name,
rootUrl: mine.url,
})),
}
},
},
Expand Down
43 changes: 6 additions & 37 deletions src/components/Layout/ConstraintSection.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import FlexSearch from 'flexsearch'
import React, { useEffect, useRef } from 'react'
import { indexWorker } from 'src/searchIndex'
import { buildSearchIndex } from 'src/buildSearchIndex'

import { ConstraintServiceContext, useMachineBus } from '../../machineBus'
import { CheckboxPopup } from '../Constraints/CheckboxPopup'
Expand Down Expand Up @@ -79,41 +78,11 @@ const ConstraintBuilder = ({ constraintConfig, color }) => {
useEffect(() => {
const buildIndex = async () => {
if (type === 'select' && searchIndex.current === null && availableValues.length > 0) {
// The configuration *must* be the same for import and export
const indexConfig = {
encode: 'advanced',
tokenize: 'reverse',
suggest: true,
cache: true,
doc: {
id: 'item',
field: 'item',
},
}

const exportConfig = {
index: true,
doc: true,
}

// @ts-ignore
const index = new FlexSearch(indexConfig)

if (typeof window !== 'undefined' && window.Worker) {
const serializedIndex = await indexWorker.index({
values: availableValues,
indexConfig,
exportConfig,
})

// @ts-ignore
index.import(serializedIndex, exportConfig)
} else {
// @ts-ignore
index.add(availableValues)
}

searchIndex.current = index
searchIndex.current = await buildSearchIndex({
docId: 'item',
docField: 'item',
values: availableValues,
})
}
}

Expand Down
27 changes: 21 additions & 6 deletions src/components/NavBar/NavBar.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Button, ButtonGroup, Classes, Menu, MenuItem, Navbar, Tab, Tabs } from '@blueprintjs/core'
import { IconNames } from '@blueprintjs/icons'
import { Select } from '@blueprintjs/select'
import React, { useState } from 'react'
import React, { useEffect, useRef, useState } from 'react'
import { CHANGE_CLASS } from 'src/actionConstants'
import { buildSearchIndex } from 'src/buildSearchIndex'
import { useServiceContext } from 'src/machineBus'
import { pluralizeFilteredCount } from 'src/utils'

Expand All @@ -26,7 +27,22 @@ export const NavigationBar = () => {
const isLightTheme = selectedTheme === 'light'

const [state, send] = useServiceContext('supervisor')
const { classView, modelClasses, classSearchIndex } = state.context
const { classView, modelClasses } = state.context
const classSearchIndex = useRef(null)

useEffect(() => {
const indexClasses = async () => {
if (modelClasses.length > 0) {
classSearchIndex.current = await buildSearchIndex({
docId: 'name',
docField: 'displayName',
values: modelClasses,
})
}
}

indexClasses()
}, [modelClasses])

const classDisplayName =
modelClasses.find((model) => model.name === classView)?.displayName ?? 'Gene'
Expand All @@ -36,14 +52,12 @@ export const NavigationBar = () => {
}

const filterQuery = (query, items) => {
if (query === '' || !classSearchIndex) {
if (query === '' || !classSearchIndex?.current) {
return items
}

// flexSearch's default result limit is set 1000, so we set it to the length of all items
const results = classSearchIndex.search(query, modelClasses.length)

return results.map((name) => ({ name }))
return classSearchIndex.current.search(query, modelClasses.length)
}

return (
Expand Down Expand Up @@ -76,6 +90,7 @@ export const NavigationBar = () => {
onItemSelect={handleClassSelect}
itemListRenderer={renderMenu}
itemListPredicate={filterQuery}
resetOnClose={true}
>
<Button
aria-label="select the views you'd like to query"
Expand Down

0 comments on commit 14dd912

Please sign in to comment.