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} />
+ + Open + documentation +
- {this.visibleGdocs.map((gdoc) => ( + {this.allGdocsToShow.map((gdoc) => (