refactor string matching (#649)
This commit is contained in:
parent
38c26f8b5c
commit
2543bdcdfc
|
@ -49,6 +49,16 @@ export function parseWordsAsTags(text: string) {
|
|||
return parseTags(taggedText)
|
||||
}
|
||||
|
||||
// TODO: fuzzy matching
|
||||
export const wordIn = (word: string, corpus: string) =>
|
||||
corpus.toLocaleLowerCase().includes(word.toLocaleLowerCase())
|
||||
|
||||
const checkAgainstQuery = (query: string, corpus: string) =>
|
||||
query.split(' ').every((word) => wordIn(word, corpus))
|
||||
|
||||
export const searchInAny = (query: string, ...fields: string[]) =>
|
||||
fields.some((field) => checkAgainstQuery(query, field))
|
||||
|
||||
// can't just do [StarterKit, Image...] because it doesn't work with cjs imports
|
||||
export const exhibitExts = [
|
||||
Blockquote,
|
||||
|
|
|
@ -7,6 +7,7 @@ import { Menu, Transition } from '@headlessui/react'
|
|||
import { Avatar } from 'web/components/avatar'
|
||||
import { Row } from 'web/components/layout/row'
|
||||
import { UserLink } from 'web/components/user-page'
|
||||
import { searchInAny } from 'common/util/parse'
|
||||
|
||||
export function FilterSelectUsers(props: {
|
||||
setSelectedUsers: (users: User[]) => void
|
||||
|
@ -35,8 +36,7 @@ export function FilterSelectUsers(props: {
|
|||
return (
|
||||
!selectedUsers.map((user) => user.name).includes(user.name) &&
|
||||
!ignoreUserIds.includes(user.id) &&
|
||||
(user.name.toLowerCase().includes(query.toLowerCase()) ||
|
||||
user.username.toLowerCase().includes(query.toLowerCase()))
|
||||
searchInAny(query, user.name, user.username)
|
||||
)
|
||||
})
|
||||
)
|
||||
|
|
|
@ -11,6 +11,7 @@ import { CreateGroupButton } from 'web/components/groups/create-group-button'
|
|||
import { useState } from 'react'
|
||||
import { useMemberGroups } from 'web/hooks/use-group'
|
||||
import { User } from 'common/user'
|
||||
import { searchInAny } from 'common/util/parse'
|
||||
|
||||
export function GroupSelector(props: {
|
||||
selectedGroup?: Group
|
||||
|
@ -22,14 +23,10 @@ export function GroupSelector(props: {
|
|||
const [isCreatingNewGroup, setIsCreatingNewGroup] = useState(false)
|
||||
|
||||
const [query, setQuery] = useState('')
|
||||
const memberGroups = useMemberGroups(creator?.id)
|
||||
const filteredGroups = memberGroups
|
||||
? query === ''
|
||||
? memberGroups
|
||||
: memberGroups.filter((group) => {
|
||||
return group.name.toLowerCase().includes(query.toLowerCase())
|
||||
})
|
||||
: []
|
||||
const memberGroups = useMemberGroups(creator?.id) ?? []
|
||||
const filteredGroups = memberGroups.filter((group) =>
|
||||
searchInAny(query, group.name)
|
||||
)
|
||||
|
||||
if (!showSelector || !creator) {
|
||||
return (
|
||||
|
|
|
@ -16,11 +16,6 @@ export type Sort =
|
|||
| 'resolve-date'
|
||||
| 'last-updated'
|
||||
|
||||
export function checkAgainstQuery(query: string, corpus: string) {
|
||||
const queryWords = query.toLowerCase().split(' ')
|
||||
return queryWords.every((word) => corpus.toLowerCase().includes(word))
|
||||
}
|
||||
|
||||
export function getSavedSort() {
|
||||
// TODO: this obviously doesn't work with SSR, common sense would suggest
|
||||
// that we should save things like this in cookies so the server has them
|
||||
|
|
|
@ -20,6 +20,7 @@ import { manaToUSD } from 'common/util/format'
|
|||
import { quadraticMatches } from 'common/quadratic-funding'
|
||||
import { Txn } from 'common/txn'
|
||||
import { useTracking } from 'web/hooks/use-tracking'
|
||||
import { searchInAny } from 'common/util/parse'
|
||||
|
||||
export async function getStaticProps() {
|
||||
const txns = await getAllCharityTxns()
|
||||
|
@ -88,10 +89,12 @@ export default function Charity(props: {
|
|||
() =>
|
||||
charities.filter(
|
||||
(charity) =>
|
||||
charity.name.toLowerCase().includes(query.toLowerCase()) ||
|
||||
charity.preview.toLowerCase().includes(query.toLowerCase()) ||
|
||||
charity.description.toLowerCase().includes(query.toLowerCase()) ||
|
||||
(charity.tags as string[])?.includes(query.toLowerCase())
|
||||
searchInAny(
|
||||
query,
|
||||
charity.name,
|
||||
charity.preview,
|
||||
charity.description
|
||||
) || (charity.tags as string[])?.includes(query.toLowerCase())
|
||||
),
|
||||
[charities, query]
|
||||
)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Answer } from 'common/answer'
|
||||
import { searchInAny } from 'common/util/parse'
|
||||
import { sortBy } from 'lodash'
|
||||
import { useState } from 'react'
|
||||
import { ContractsGrid } from 'web/components/contract/contracts-list'
|
||||
|
@ -28,22 +29,14 @@ export default function ContractSearchFirestore(props: {
|
|||
const [sort, setSort] = useState(initialSort || 'newest')
|
||||
const [query, setQuery] = useState(initialQuery)
|
||||
|
||||
const queryWords = query.toLowerCase().split(' ')
|
||||
function check(corpus: string) {
|
||||
return queryWords.every((word) => corpus.toLowerCase().includes(word))
|
||||
}
|
||||
|
||||
let matches = (contracts ?? []).filter(
|
||||
(c) =>
|
||||
check(c.question) ||
|
||||
check(c.creatorName) ||
|
||||
check(c.creatorUsername) ||
|
||||
check(c.lowercaseTags.map((tag) => `#${tag}`).join(' ')) ||
|
||||
check(
|
||||
((c as any).answers ?? [])
|
||||
.map((answer: Answer) => answer.text)
|
||||
.join(' ')
|
||||
)
|
||||
let matches = (contracts ?? []).filter((c) =>
|
||||
searchInAny(
|
||||
query,
|
||||
c.question,
|
||||
c.creatorName,
|
||||
c.lowercaseTags.map((tag) => `#${tag}`).join(' '),
|
||||
((c as any).answers ?? []).map((answer: Answer) => answer.text).join(' ')
|
||||
)
|
||||
)
|
||||
|
||||
if (sort === 'newest') {
|
||||
|
|
|
@ -40,10 +40,7 @@ import React, { useEffect, useState } from 'react'
|
|||
import { GroupChat } from 'web/components/groups/group-chat'
|
||||
import { LoadingIndicator } from 'web/components/loading-indicator'
|
||||
import { Modal } from 'web/components/layout/modal'
|
||||
import {
|
||||
checkAgainstQuery,
|
||||
getSavedSort,
|
||||
} from 'web/hooks/use-sort-and-query-params'
|
||||
import { getSavedSort } from 'web/hooks/use-sort-and-query-params'
|
||||
import { ChoicesToggleGroup } from 'web/components/choices-toggle-group'
|
||||
import { toast } from 'react-hot-toast'
|
||||
import { useCommentsOnGroup } from 'web/hooks/use-comments'
|
||||
|
@ -56,6 +53,7 @@ import { SearchIcon } from '@heroicons/react/outline'
|
|||
import { useTipTxns } from 'web/hooks/use-tip-txns'
|
||||
import { JoinOrLeaveGroupButton } from 'web/components/groups/groups-button'
|
||||
import { OnlineUserList } from 'web/components/online-user-list'
|
||||
import { searchInAny } from 'common/util/parse'
|
||||
|
||||
export const getStaticProps = fromPropz(getStaticPropz)
|
||||
export async function getStaticPropz(props: { params: { slugs: string[] } }) {
|
||||
|
@ -446,9 +444,8 @@ function GroupMemberSearch(props: { members: User[]; group: Group }) {
|
|||
}
|
||||
|
||||
// TODO use find-active-contracts to sort by?
|
||||
const matches = sortBy(members, [(member) => member.name]).filter(
|
||||
(m) =>
|
||||
checkAgainstQuery(query, m.name) || checkAgainstQuery(query, m.username)
|
||||
const matches = sortBy(members, [(member) => member.name]).filter((m) =>
|
||||
searchInAny(query, m.name, m.username)
|
||||
)
|
||||
const matchLimit = 25
|
||||
|
||||
|
|
|
@ -12,12 +12,12 @@ import { useUser } from 'web/hooks/use-user'
|
|||
import { groupPath, listAllGroups } from 'web/lib/firebase/groups'
|
||||
import { getUser, User } from 'web/lib/firebase/users'
|
||||
import { Tabs } from 'web/components/layout/tabs'
|
||||
import { checkAgainstQuery } from 'web/hooks/use-sort-and-query-params'
|
||||
import { SiteLink } from 'web/components/site-link'
|
||||
import clsx from 'clsx'
|
||||
import { Avatar } from 'web/components/avatar'
|
||||
import { JoinOrLeaveGroupButton } from 'web/components/groups/groups-button'
|
||||
import { UserLink } from 'web/components/user-page'
|
||||
import { searchInAny } from 'common/util/parse'
|
||||
|
||||
export async function getStaticProps() {
|
||||
const groups = await listAllGroups().catch((_) => [])
|
||||
|
@ -71,11 +71,13 @@ export default function Groups(props: {
|
|||
const matches = sortBy(groups, [
|
||||
(group) => -1 * group.contractIds.length,
|
||||
(group) => -1 * group.memberIds.length,
|
||||
]).filter(
|
||||
(g) =>
|
||||
checkAgainstQuery(query, g.name) ||
|
||||
checkAgainstQuery(query, g.about || '') ||
|
||||
checkAgainstQuery(query, creatorsDict[g.creatorId].username)
|
||||
]).filter((g) =>
|
||||
searchInAny(
|
||||
query,
|
||||
g.name,
|
||||
g.about || '',
|
||||
creatorsDict[g.creatorId].username
|
||||
)
|
||||
)
|
||||
|
||||
const matchesOrderedByRecentActivity = sortBy(groups, [
|
||||
|
@ -84,11 +86,13 @@ export default function Groups(props: {
|
|||
(group.mostRecentChatActivityTime ??
|
||||
group.mostRecentContractAddedTime ??
|
||||
group.mostRecentActivityTime),
|
||||
]).filter(
|
||||
(g) =>
|
||||
checkAgainstQuery(query, g.name) ||
|
||||
checkAgainstQuery(query, g.about || '') ||
|
||||
checkAgainstQuery(query, creatorsDict[g.creatorId].username)
|
||||
]).filter((g) =>
|
||||
searchInAny(
|
||||
query,
|
||||
g.name,
|
||||
g.about || '',
|
||||
creatorsDict[g.creatorId].username
|
||||
)
|
||||
)
|
||||
|
||||
// Not strictly necessary, but makes the "hold delete" experience less laggy
|
||||
|
|
Loading…
Reference in New Issue
Block a user