aboutsummaryrefslogtreecommitdiff
path: root/plugins/base/frontend/src/main
diff options
context:
space:
mode:
authorMarcin Aman <maman@virtuslab.com>2020-07-30 15:05:06 +0200
committerPaweł Marks <Kordyjan@users.noreply.github.com>2020-08-21 15:40:12 +0200
commit3c07bc1966c85de3351602c4e8798fa507c40e49 (patch)
treeef39ea18a4ec699e4cab9dc55489b43fccb1e247 /plugins/base/frontend/src/main
parentc2b02c1fc17b839075b7cb6fd42498a519473fae (diff)
downloaddokka-3c07bc1966c85de3351602c4e8798fa507c40e49.tar.gz
dokka-3c07bc1966c85de3351602c4e8798fa507c40e49.tar.bz2
dokka-3c07bc1966c85de3351602c4e8798fa507c40e49.zip
Create navigation search component
Diffstat (limited to 'plugins/base/frontend/src/main')
-rw-r--r--plugins/base/frontend/src/main/components/navigationPaneSearch/clear.svg3
-rw-r--r--plugins/base/frontend/src/main/components/navigationPaneSearch/navigationPaneSearch.scss37
-rw-r--r--plugins/base/frontend/src/main/components/navigationPaneSearch/navigationPaneSearch.tsx73
-rw-r--r--plugins/base/frontend/src/main/components/root.tsx9
-rw-r--r--plugins/base/frontend/src/main/components/search/dokkaFuzzyFilter.tsx18
-rw-r--r--plugins/base/frontend/src/main/components/search/search.scss14
-rw-r--r--plugins/base/frontend/src/main/components/search/search.tsx1
-rw-r--r--plugins/base/frontend/src/main/components/search/types.ts1
-rw-r--r--plugins/base/frontend/src/main/scss/index.scss3
9 files changed, 144 insertions, 15 deletions
diff --git a/plugins/base/frontend/src/main/components/navigationPaneSearch/clear.svg b/plugins/base/frontend/src/main/components/navigationPaneSearch/clear.svg
new file mode 100644
index 00000000..ad6a2026
--- /dev/null
+++ b/plugins/base/frontend/src/main/components/navigationPaneSearch/clear.svg
@@ -0,0 +1,3 @@
+<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M11.1374 1.80464L6.94205 5.99996L11.1374 10.1953L10.1947 11.138L5.99935 6.94267L1.80403 11.138L0.861328 10.1953L5.05664 5.99996L0.861328 1.80464L1.80403 0.861938L5.99935 5.05725L10.1947 0.861938L11.1374 1.80464Z" fill="#637282"/>
+</svg>
diff --git a/plugins/base/frontend/src/main/components/navigationPaneSearch/navigationPaneSearch.scss b/plugins/base/frontend/src/main/components/navigationPaneSearch/navigationPaneSearch.scss
new file mode 100644
index 00000000..b5714ca4
--- /dev/null
+++ b/plugins/base/frontend/src/main/components/navigationPaneSearch/navigationPaneSearch.scss
@@ -0,0 +1,37 @@
+@import "src/main/scss/index.scss";
+
+$defaultHeight: 40px;
+
+div#paneSearch {
+
+ width: 248px;
+ margin: 0 auto;
+
+ input#navigation-pane-search {
+ background: $white;
+ border: 1px solid $grey-border;
+ box-sizing: border-box;
+ border-radius: 4px;
+ padding: 8px;
+ height: $defaultHeight;
+ }
+
+ .navigation-pane-search {
+ width: 100% !important;
+ padding-top: 16px;
+ }
+
+ div.paneSearchInputWrapper {
+ position: relative;
+ span.paneSearchInputClearIcon {
+ position: absolute;
+ top: calc(50% + 2px); //Just to include a border
+ right: 8px;
+ cursor: pointer;
+ }
+ }
+}
+
+.navigation-pane-popup {
+ margin-top: 1.2em;
+} \ No newline at end of file
diff --git a/plugins/base/frontend/src/main/components/navigationPaneSearch/navigationPaneSearch.tsx b/plugins/base/frontend/src/main/components/navigationPaneSearch/navigationPaneSearch.tsx
new file mode 100644
index 00000000..3174b023
--- /dev/null
+++ b/plugins/base/frontend/src/main/components/navigationPaneSearch/navigationPaneSearch.tsx
@@ -0,0 +1,73 @@
+import React, { useCallback, useState, useEffect } from 'react';
+import {Select, List } from '@jetbrains/ring-ui';
+import { DokkaFuzzyFilterComponent } from '../search/dokkaFuzzyFilter';
+import { IWindow, Option } from '../search/types';
+import './navigationPaneSearch.scss';
+import ClearIcon from 'react-svg-loader!./clear.svg';
+
+export const NavigationPaneSearch = () => {
+ const defaultWidth = 300
+
+ const [navigationList, setNavigationList] = useState<Option[]>([]);
+ const [selected, onSelected] = useState<Option | null>(null);
+ const [minWidth, setMinWidth] = useState<number>(defaultWidth);
+ const [filterValue, setFilterValue] = useState<string>('')
+
+ const onChangeSelected = useCallback(
+ (element: Option) => {
+ window.location.replace(`${(window as IWindow).pathToRoot}${element.location}`)
+ onSelected(element);
+ },
+ [selected]
+ );
+
+ const onFilter = (filterValue: string, filteredRecords?: Option[]) => {
+ if(filteredRecords){
+ const requiredWidth = Math.max(...filteredRecords.map(e => e.label.length*9), defaultWidth)
+ setMinWidth(requiredWidth)
+ }
+ setFilterValue(filterValue)
+ }
+
+ const onClearClick = () => {
+ setFilterValue('')
+ }
+
+ useEffect(() => {
+ const pathToRoot = (window as IWindow).pathToRoot
+ const url = pathToRoot.endsWith('/') ? `${pathToRoot}scripts/navigation-pane.json` : `${pathToRoot}/scripts/navigation-pane.json`
+ fetch(url)
+ .then(response => response.json())
+ .then((result) => {
+ setNavigationList(result.map((record: Option) => {
+ return {
+ ...record,
+ rgItemType: List.ListProps.Type.CUSTOM
+ }
+ }))
+ },
+ (error) => {
+ console.error('failed to fetch navigationPane data', error)
+ setNavigationList([])
+ })
+ }, [])
+
+
+ return <div className={"paneSearchInputWrapper"}>
+ <DokkaFuzzyFilterComponent
+ id="navigation-pane-search"
+ className="navigation-pane-search"
+ inputPlaceholder="Title filter"
+ clear={true}
+ type={Select.Type.INPUT_WITHOUT_CONTROLS}
+ filter={{fuzzy:true, value: filterValue}}
+ selected={selected}
+ data={navigationList}
+ popupClassName={"navigation-pane-popup"}
+ onSelect={onChangeSelected}
+ onFilter={onFilter}
+ minWidth={minWidth}
+ />
+ <span className={"paneSearchInputClearIcon"} onClick={onClearClick}><ClearIcon /></span>
+ </div>
+} \ No newline at end of file
diff --git a/plugins/base/frontend/src/main/components/root.tsx b/plugins/base/frontend/src/main/components/root.tsx
index 70ed9550..9f3ecba9 100644
--- a/plugins/base/frontend/src/main/components/root.tsx
+++ b/plugins/base/frontend/src/main/components/root.tsx
@@ -4,15 +4,24 @@ import RedBox from 'redbox-react';
import App from "./app";
import './app/index.scss';
+import { NavigationPaneSearch } from './navigationPaneSearch/navigationPaneSearch';
const appEl = document.getElementById('searchBar');
const rootEl = document.createElement('div');
+const renderNavigationPane = () => {
+ render(
+ <NavigationPaneSearch />,
+ document.getElementById('paneSearch')
+ )
+}
+
let renderApp = () => {
render(
<App/>,
rootEl
);
+ renderNavigationPane();
};
// @ts-ignore
diff --git a/plugins/base/frontend/src/main/components/search/dokkaFuzzyFilter.tsx b/plugins/base/frontend/src/main/components/search/dokkaFuzzyFilter.tsx
index 725fbaee..2d9dcb3d 100644
--- a/plugins/base/frontend/src/main/components/search/dokkaFuzzyFilter.tsx
+++ b/plugins/base/frontend/src/main/components/search/dokkaFuzzyFilter.tsx
@@ -39,10 +39,20 @@ const highlightMatchedPhrases = (records: OptionWithSearchResult[]): OptionWithH
}
export class DokkaFuzzyFilterComponent extends Select {
+ componentDidUpdate(prevProps, prevState) {
+ super.componentDidUpdate(prevProps, prevState)
+ if(this.props.filter && this.state.filterValue != this.props.filter.value){
+ this.setState({
+ filterValue: this.props.filter.value,
+ })
+ }
+ }
+
getListItems(rawFilterString: string, _: Option[]) {
+ const filterPhrase = (rawFilterString ? rawFilterString : '').trim()
const matchedRecords = this.props.data
.map((record: Option) => {
- const bySearchKey = fuzzyHighlight(rawFilterString.trim(), record.searchKey, false)
+ const bySearchKey = fuzzyHighlight(filterPhrase, record.searchKey, false)
if(bySearchKey.matched){
return {
...bySearchKey,
@@ -51,13 +61,15 @@ export class DokkaFuzzyFilterComponent extends Select {
}
}
return {
- ...fuzzyHighlight(rawFilterString.trim(), record.name, false),
+ ...fuzzyHighlight(filterPhrase, record.name, false),
...record,
rank: SearchRank.NameMatch
}
})
.filter((record: OptionWithSearchResult) => record.matched)
- return highlightMatchedPhrases(orderRecords(matchedRecords, rawFilterString))
+ this.props.onFilter(filterPhrase, matchedRecords)
+
+ return highlightMatchedPhrases(orderRecords(matchedRecords, filterPhrase))
}
} \ No newline at end of file
diff --git a/plugins/base/frontend/src/main/components/search/search.scss b/plugins/base/frontend/src/main/components/search/search.scss
index 1068fe7a..e708ef84 100644
--- a/plugins/base/frontend/src/main/components/search/search.scss
+++ b/plugins/base/frontend/src/main/components/search/search.scss
@@ -14,20 +14,12 @@
min-width: calc(100% - 360px) !important;
}
-.indented {
- text-indent: 10px;
-}
-
-.disabled {
- color: gray;
-}
-
.template-wrapper {
+ height: 32px;
display: grid;
grid-template-columns: auto auto;
-
- span.phraseHighlight {
- font-weight: bold;
+ span {
+ line-height: 32px;
}
}
diff --git a/plugins/base/frontend/src/main/components/search/search.tsx b/plugins/base/frontend/src/main/components/search/search.tsx
index c7976edb..ef26c662 100644
--- a/plugins/base/frontend/src/main/components/search/search.tsx
+++ b/plugins/base/frontend/src/main/components/search/search.tsx
@@ -20,6 +20,7 @@ const WithFuzzySearchFilterComponent: React.FC<Props> = ({data}: Props) => {
<div className="search-container">
<div className="search">
<DokkaFuzzyFilterComponent
+ id="pages-search"
selectedLabel="Search"
label="Please type page name"
filter={true}
diff --git a/plugins/base/frontend/src/main/components/search/types.ts b/plugins/base/frontend/src/main/components/search/types.ts
index 922935bd..11e2edf8 100644
--- a/plugins/base/frontend/src/main/components/search/types.ts
+++ b/plugins/base/frontend/src/main/components/search/types.ts
@@ -6,7 +6,6 @@ export type Page = {
location: string;
searchKey: string;
description: string;
- disabled: boolean;
}
export type Option = Page & {
diff --git a/plugins/base/frontend/src/main/scss/index.scss b/plugins/base/frontend/src/main/scss/index.scss
index 74af970d..18e2861b 100644
--- a/plugins/base/frontend/src/main/scss/index.scss
+++ b/plugins/base/frontend/src/main/scss/index.scss
@@ -1 +1,4 @@
@import "~@jetbrains/ring-ui/components/global/variables.css";
+
+$white: #FFFFFF;
+$grey-border: #A6AFBA