From b14e0617a126ed3b8b9256542ce857c060e3e295 Mon Sep 17 00:00:00 2001 From: Marcin Aman Date: Wed, 29 Jul 2020 17:32:13 +0200 Subject: Split into files and move svg to external one --- .../main/components/search/dokkaFuzzyFilter.tsx | 63 +++++++++++ .../main/components/search/dokkaSearchAnchor.tsx | 13 +++ .../frontend/src/main/components/search/search.tsx | 116 +-------------------- .../src/main/components/search/searchIcon.svg | 3 + .../src/main/components/search/searchResultRow.tsx | 24 +++++ .../frontend/src/main/components/search/types.ts | 19 +++- .../frontend/src/main/types/@jetbrains/index.d.ts | 6 -- 7 files changed, 123 insertions(+), 121 deletions(-) create mode 100644 plugins/base/frontend/src/main/components/search/dokkaFuzzyFilter.tsx create mode 100644 plugins/base/frontend/src/main/components/search/dokkaSearchAnchor.tsx create mode 100644 plugins/base/frontend/src/main/components/search/searchIcon.svg create mode 100644 plugins/base/frontend/src/main/components/search/searchResultRow.tsx (limited to 'plugins/base/frontend/src') diff --git a/plugins/base/frontend/src/main/components/search/dokkaFuzzyFilter.tsx b/plugins/base/frontend/src/main/components/search/dokkaFuzzyFilter.tsx new file mode 100644 index 00000000..725fbaee --- /dev/null +++ b/plugins/base/frontend/src/main/components/search/dokkaFuzzyFilter.tsx @@ -0,0 +1,63 @@ +import {Select} from "@jetbrains/ring-ui"; +import {Option, OptionWithHighlightComponent, OptionWithSearchResult, SearchRank} from "./types"; +import fuzzyHighlight from '@jetbrains/ring-ui/components/global/fuzzy-highlight.js' +import React from "react"; +import {SearchResultRow} from "./searchResultRow"; + +const orderRecords = (records: OptionWithSearchResult[], searchPhrase: string): OptionWithSearchResult[] => { + return records.sort((a: OptionWithSearchResult, b: OptionWithSearchResult) => { + //Prefer higher rank + const byRank = b.rank - a.rank + if(byRank !== 0){ + return byRank + } + //Prefer exact matches + const aIncludes = a.name.toLowerCase().includes(searchPhrase.toLowerCase()) ? 1 : 0 + const bIncludes = b.name.toLowerCase().includes(searchPhrase.toLowerCase()) ? 1 : 0 + const byIncludes = bIncludes - aIncludes + if(byIncludes != 0){ + return byIncludes + } + + //Prefer matches that are closer + const byFirstMatchedPosition = a.highlight.indexOf("**") - b.highlight.indexOf("**") + if(byFirstMatchedPosition == 0) { + return a.name.toLowerCase().localeCompare(b.name.toLowerCase()) + } + return byFirstMatchedPosition + }) +} + +const highlightMatchedPhrases = (records: OptionWithSearchResult[]): OptionWithHighlightComponent[] => { + // @ts-ignore + return records.map(record => { + return { + ...record, + template: + } + }) +} + +export class DokkaFuzzyFilterComponent extends Select { + getListItems(rawFilterString: string, _: Option[]) { + const matchedRecords = this.props.data + .map((record: Option) => { + const bySearchKey = fuzzyHighlight(rawFilterString.trim(), record.searchKey, false) + if(bySearchKey.matched){ + return { + ...bySearchKey, + ...record, + rank: SearchRank.SearchKeyMatch + } + } + return { + ...fuzzyHighlight(rawFilterString.trim(), record.name, false), + ...record, + rank: SearchRank.NameMatch + } + }) + .filter((record: OptionWithSearchResult) => record.matched) + + return highlightMatchedPhrases(orderRecords(matchedRecords, rawFilterString)) + } +} \ No newline at end of file diff --git a/plugins/base/frontend/src/main/components/search/dokkaSearchAnchor.tsx b/plugins/base/frontend/src/main/components/search/dokkaSearchAnchor.tsx new file mode 100644 index 00000000..ad0b5f8f --- /dev/null +++ b/plugins/base/frontend/src/main/components/search/dokkaSearchAnchor.tsx @@ -0,0 +1,13 @@ +import React from "react"; +import SearchIcon from 'react-svg-loader!./searchIcon.svg'; + +export const DokkaSearchAnchor = ({wrapperProps, buttonProps, popup}: any) => { + return ( + + + {popup} + + ) +} \ No newline at end of file diff --git a/plugins/base/frontend/src/main/components/search/search.tsx b/plugins/base/frontend/src/main/components/search/search.tsx index b4c5b1cd..c7976edb 100644 --- a/plugins/base/frontend/src/main/components/search/search.tsx +++ b/plugins/base/frontend/src/main/components/search/search.tsx @@ -1,107 +1,10 @@ import React, {useCallback, useState} from 'react'; import {Select, List} from '@jetbrains/ring-ui'; -import fuzzyHighlight from '@jetbrains/ring-ui/components/global/fuzzy-highlight.js' import '@jetbrains/ring-ui/components/input-size/input-size.scss'; import './search.scss'; -import {IWindow, Option, Props, Page} from "./types"; - -enum SearchRank { - SearchKeyMatch = 1, - NameMatch = 0 -} -type OptionWithSearchResult = Option & { - matched: boolean, - highlight: string, - rank: SearchRank -} - -type OptionWithHighlightComponent = Option & { - name: React.FC -} - -type SearchProps = { - searchResult: OptionWithSearchResult, -} - -const orderRecords = (records: OptionWithSearchResult[], searchPhrase: string): OptionWithSearchResult[] => { - return records.sort((a: OptionWithSearchResult, b: OptionWithSearchResult) => { - //Prefer higher rank - const byRank = b.rank - a.rank - if(byRank !== 0){ - return byRank - } - //Prefer exact matches - const aIncludes = a.name.toLowerCase().includes(searchPhrase.toLowerCase()) ? 1 : 0 - const bIncludes = b.name.toLowerCase().includes(searchPhrase.toLowerCase()) ? 1 : 0 - const byIncludes = bIncludes - aIncludes - if(byIncludes != 0){ - return byIncludes - } - - //Prefer matches that are closer - const byFirstMatchedPosition = a.highlight.indexOf("**") - b.highlight.indexOf("**") - if(byFirstMatchedPosition == 0) { - return a.name.toLowerCase().localeCompare(b.name.toLowerCase()) - } - return byFirstMatchedPosition - }) -} - -const SearchResultRow: React.FC = ({searchResult}: SearchProps) => { - const signatureFromSearchResult = (searchResult: OptionWithSearchResult): string => { - if(searchResult.rank == SearchRank.SearchKeyMatch){ - return searchResult.name.replace(searchResult.searchKey, searchResult.highlight) - } - return searchResult.highlight - } - - const renderHighlightMarkersAsHtml = (record: string): string => { - return record.replace(/\*\*(.*?)\*\*/g, '$1') - } - - return ( -
- - {searchResult.description} -
- ) -} - -const highlightMatchedPhrases = (records: OptionWithSearchResult[]): OptionWithHighlightComponent[] => { - // @ts-ignore - return records.map(record => { - return { - ...record, - template: - } - }) -} - -class DokkaFuzzyFilterComponent extends Select { - getListItems(rawFilterString: string, _: Option[]) { - const matchedRecords = this.props.data - .map((record: Option) => { - const bySearchKey = fuzzyHighlight(rawFilterString.trim(), record.searchKey, true) - if(bySearchKey.matched){ - return { - ...bySearchKey, - ...record, - rank: SearchRank.SearchKeyMatch - } - } - return { - ...fuzzyHighlight(rawFilterString.trim(), record.name), - ...record, - rank: SearchRank.NameMatch - } - }) - .filter((record: OptionWithSearchResult) => record.matched) - - return highlightMatchedPhrases(orderRecords(matchedRecords, rawFilterString)) - } -} +import {IWindow, Option, Props} from "./types"; +import {DokkaSearchAnchor} from "./dokkaSearchAnchor"; +import {DokkaFuzzyFilterComponent} from "./dokkaFuzzyFilter"; const WithFuzzySearchFilterComponent: React.FC = ({data}: Props) => { const [selected, onSelected] = useState