diff --git a/adminSiteClient/GdocsIndexPage.scss b/adminSiteClient/GdocsIndexPage.scss
index ef11a87738a..d3a016730d7 100644
--- a/adminSiteClient/GdocsIndexPage.scss
+++ b/adminSiteClient/GdocsIndexPage.scss
@@ -61,6 +61,10 @@
width: 100%;
}
+.gdoc-index__help-link {
+ margin-right: 8px;
+}
+
.gdoc-index-filter-checkbox {
cursor: pointer;
margin-right: 16px;
diff --git a/adminSiteClient/GdocsIndexPage.tsx b/adminSiteClient/GdocsIndexPage.tsx
index 1a13af14dc4..66e63e3d975 100644
--- a/adminSiteClient/GdocsIndexPage.tsx
+++ b/adminSiteClient/GdocsIndexPage.tsx
@@ -8,9 +8,18 @@ import {
faLightbulb,
faNewspaper,
faPuzzlePiece,
+ faQuestion,
} from "@fortawesome/free-solid-svg-icons"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome/index.js"
-import { Tag, OwidGdocInterface, OwidGdocType } from "@ourworldindata/utils"
+import {
+ Tag,
+ OwidGdocInterface,
+ OwidGdocType,
+ SearchWord,
+ buildSearchWordsFromSearchString,
+ filterFunctionForSearchWords,
+ spansToUnformattedPlainText,
+} from "@ourworldindata/utils"
import { Route, RouteComponentProps } from "react-router-dom"
import { Link } from "./Link.js"
import { GdocsAdd } from "./GdocsAdd.js"
@@ -18,7 +27,6 @@ import { observer } from "mobx-react"
import { GdocsStoreContext } from "./GdocsStore.js"
import { computed, observable } from "mobx"
import { BAKED_BASE_URL } from "../settings/clientSettings.js"
-import fuzzysort from "fuzzysort"
import { GdocsEditLink } from "./GdocsEditLink.js"
const iconGdocTypeMap = {
@@ -27,11 +35,6 @@ const iconGdocTypeMap = {
[OwidGdocType.TopicPage]: ,
}
-interface Searchable {
- gdoc: OwidGdocInterface
- term?: Fuzzysort.Prepared
-}
-
@observer
class GdocsIndexPageSearch extends React.Component<{
filters: Record
@@ -106,6 +109,11 @@ export class GdocsIndexPage extends React.Component {
@observable search = { value: "" }
+ @computed get searchWords(): SearchWord[] {
+ const { search } = this
+ return buildSearchWordsFromSearchString(search.value)
+ }
+
async componentDidMount(): Promise {
await this.context?.fetchTags()
await this.context?.fetchGdocs()
@@ -116,27 +124,10 @@ export class GdocsIndexPage extends React.Component {
return this.context?.availableTags || []
}
- @computed get searchIndex(): Searchable[] {
- if (!this.context) return []
- const searchIndex: Searchable[] = []
- for (const gdoc of this.context.gdocs) {
- searchIndex.push({
- gdoc,
- term: fuzzysort.prepare(
- `${gdoc.content.title} ${gdoc.content.authors?.join(
- " "
- )} ${gdoc.tags?.map(({ name }) => name).join(" ")}`
- ),
- })
- }
-
- return searchIndex
- }
-
- @computed
- get visibleGdocs(): OwidGdocInterface[] {
- const { context, search, searchIndex } = this
+ @computed get allGdocsToShow(): OwidGdocInterface[] {
+ const { searchWords, context } = this
if (!context) return []
+
// Don't filter unless at least one filter is active
const shouldUseFilters = !!Object.values(this.filters).find(
(isFilterActive) => isFilterActive
@@ -149,31 +140,29 @@ export class GdocsIndexPage extends React.Component {
!gdoc.content.type || !!this.filters[gdoc.content.type]
)
: context.gdocs
- if (!search.value) return filteredByType
-
- const fuzzysorted = fuzzysort.go(search.value, searchIndex, {
- limit: 50,
- key: "term",
- })
-
- const uniqueFiltered = fuzzysorted.reduce(
- (acc: Set, { obj: { gdoc } }) => {
- const shouldInclude =
- // Don't filter unless at least one filter is active
- !shouldUseFilters ||
- !gdoc.content.type ||
- this.filters[gdoc.content.type]
-
- if (shouldInclude) {
- acc.add(gdoc)
- }
- return acc
- },
- new Set()
- )
-
- return [...uniqueFiltered]
+ if (searchWords.length > 0) {
+ const filterFn = filterFunctionForSearchWords(
+ searchWords,
+ (gdoc: OwidGdocInterface) => [
+ gdoc.content.title,
+ gdoc.content.subtitle,
+ gdoc.content.summary
+ ? spansToUnformattedPlainText(
+ gdoc.content.summary.flatMap(
+ (block) => block.value
+ )
+ )
+ : undefined,
+ gdoc.slug,
+ gdoc.content.authors?.join(" "),
+ gdoc.tags?.map(({ name }) => name).join(" "),
+ ]
+ )
+ return filteredByType.filter(filterFn)
+ } else {
+ return filteredByType
+ }
}
render() {
@@ -186,6 +175,15 @@ export class GdocsIndexPage extends React.Component {
search={this.search}
/>
- {this.visibleGdocs.map((gdoc) => (
+ {this.allGdocsToShow.map((gdoc) => (