diff --git a/src/common-elements/index.ts b/src/common-elements/index.ts index 96fe0f6a..5c9ec542 100644 --- a/src/common-elements/index.ts +++ b/src/common-elements/index.ts @@ -8,3 +8,4 @@ export * from './dropdown'; export * from './mixins'; export * from './tabs'; export * from './samples'; +export * from './perfect-scrollbar'; diff --git a/src/components/Endpoint/styled.elements.ts b/src/components/Endpoint/styled.elements.ts index b2858e6e..a57219eb 100644 --- a/src/components/Endpoint/styled.elements.ts +++ b/src/components/Endpoint/styled.elements.ts @@ -3,6 +3,7 @@ import styled, { withProps } from '../../styled-components'; export const OperationEndpointWrap = styled.div` cursor: pointer; position: relative; + margin-bottom: 5px; `; export const ServerRelativeURL = styled.span` diff --git a/src/components/Redoc/Redoc.tsx b/src/components/Redoc/Redoc.tsx index f6de6a62..547a8121 100644 --- a/src/components/Redoc/Redoc.tsx +++ b/src/components/Redoc/Redoc.tsx @@ -24,7 +24,7 @@ export class Redoc extends React.Component { }; componentDidMount() { - this.props.store.menu.updateOnHash(); + this.props.store.onDidMount(); } componentWillUnmount() { diff --git a/src/components/SearchBox/SearchBox.tsx b/src/components/SearchBox/SearchBox.tsx index 3f25fc7a..ab4557fc 100644 --- a/src/components/SearchBox/SearchBox.tsx +++ b/src/components/SearchBox/SearchBox.tsx @@ -82,6 +82,8 @@ export interface SearchBoxProps { marker: MarkerService; getItemById: (id: string) => IMenuItem | undefined; onActivate: (item: IMenuItem) => void; + + className?: string; } export interface SearchBoxState { @@ -89,6 +91,11 @@ export interface SearchBoxState { term: string; } +interface SearchResult { + item: IMenuItem; + score: number; +} + export class SearchBox extends React.PureComponent { constructor(props) { super(props); @@ -145,8 +152,14 @@ export class SearchBox extends React.PureComponent this.props.getItemById(res.id)); - items.sort((a, b) => (a.depth > b.depth ? 1 : a.depth < b.depth ? -1 : 0)); + const results: SearchResult[] = this.state.results.map(res => ({ + item: this.props.getItemById(res.id), + score: res.score, + })); + results.sort( + (a, b) => + a.item.depth > b.item.depth ? 1 : a.item.depth < b.item.depth ? -1 : b.score - a.score, + ); return (
@@ -158,14 +171,14 @@ export class SearchBox extends React.PureComponent - {items.length > 0 && ( + {results.length > 0 && ( - {items.map(item => ( + {results.map(res => ( ))} diff --git a/src/components/index.ts b/src/components/index.ts index 60cfee17..733fb8e8 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -2,6 +2,7 @@ export * from './RedocStandalone'; export * from './Redoc/Redoc'; // export * from './Redoc/elements'; export * from './Schema/'; +export * from './SearchBox/SearchBox'; export * from './Operation/Operation'; export * from './RedocStandalone'; diff --git a/src/services/AppStore.ts b/src/services/AppStore.ts index 2f184d58..f8e03def 100644 --- a/src/services/AppStore.ts +++ b/src/services/AppStore.ts @@ -59,15 +59,21 @@ export class AppStore { this.spec = new SpecStore(spec, specUrl, this.options); this.menu = new MenuStore(this.spec, this.scroll); - this.search = new SearchStore(this.spec); + this.search = new SearchStore(); + this.search.indexItems(this.menu.items); + this.search.done(); this.disposer = observe(this.menu, 'activeItemIdx', change => { this.updateMarkOnMenu(change.newValue as number); }); } + onDidMount() { + this.menu.updateOnHash(); + this.updateMarkOnMenu(this.menu.activeItemIdx); + } + updateMarkOnMenu(idx: number) { - console.log('update marker'); const start = Math.max(0, idx); const end = Math.min(this.menu.flatItems.length, start + 5); diff --git a/src/services/MarkerService.ts b/src/services/MarkerService.ts index 8c956974..5c3462e3 100644 --- a/src/services/MarkerService.ts +++ b/src/services/MarkerService.ts @@ -34,7 +34,6 @@ export class MarkerService { } mark(term?: string) { - console.log('mark', term); if (!term && !this.prevTerm) return; this.map.forEach(val => { val.unmark(); diff --git a/src/services/MenuStore.ts b/src/services/MenuStore.ts index 7070c8b1..a99632fd 100644 --- a/src/services/MenuStore.ts +++ b/src/services/MenuStore.ts @@ -16,6 +16,7 @@ export interface IMenuItem { id: string; absoluteIdx?: number; name: string; + description?: string; depth: number; active: boolean; items: IMenuItem[]; diff --git a/src/services/SearchStore.ts b/src/services/SearchStore.ts index 4fc4f596..c8fba06d 100644 --- a/src/services/SearchStore.ts +++ b/src/services/SearchStore.ts @@ -1,21 +1,18 @@ -import { SpecStore } from '../index'; -import { GroupModel, OperationModel } from './models'; +import { OperationModel } from './models'; import worker from './SearchWorker.worker'; +import { IMenuItem } from './MenuStore'; export class SearchStore { searchWorker = new worker(); - constructor(private spec: SpecStore) { - this.indexGroups(this.spec.operationGroups); - this.done(); - } + constructor() {} - indexGroups(groups: Array) { + indexItems(groups: Array) { groups.forEach(group => { if (group.type !== 'group') { this.add(group.name, group.description || '', group.id); } - this.indexGroups(group.items); + this.indexItems(group.items); }); } diff --git a/src/services/SearchWorker.worker.ts b/src/services/SearchWorker.worker.ts index 13b4d3c8..170850ec 100644 --- a/src/services/SearchWorker.worker.ts +++ b/src/services/SearchWorker.worker.ts @@ -13,6 +13,10 @@ export interface SearchDocument { id: string; } +export interface SearchResult extends SearchDocument { + score: number; +} + const store: { [id: string]: SearchDocument } = {}; let resolveIndex: (v: lunr.Index) => void; @@ -39,7 +43,7 @@ export async function done() { resolveIndex(builder.build()); } -export async function search(q: string): Promise { +export async function search(q: string): Promise { if (q.trim().length === 0) { return []; } @@ -54,5 +58,5 @@ export async function search(q: string): Promise { t.term(exp, {}); }); }) - .map(res => store[res.ref]); + .map(res => ({ ...store[res.ref], score: res.score })); }