diff --git a/src/components/fields-query.tsx b/src/components/fields-query.tsx index 19d4d92..4814b96 100644 --- a/src/components/fields-query.tsx +++ b/src/components/fields-query.tsx @@ -1,71 +1,73 @@ import React, { ChangeEvent, useCallback, useState } from 'react'; -import { Box, Button, TextField, Select, MenuItem, SelectChangeEvent } from '@mui/material'; +import { + Box, + Button, + TextField, + Select, + MenuItem, + SelectChangeEvent +} from '@mui/material'; import AddIcon from '@mui/icons-material/Add'; import DeleteIcon from '@mui/icons-material/Delete'; import { IndexedColumnId } from './result'; - export enum Composition { And = 'AND', - Or = 'OR', -}; - + Or = 'OR' +} type CompositionMode = { - type: Composition, - label: string, + type: Composition; + label: string; }; - type Field = { - id: IndexedColumnId, - label: string, + id: IndexedColumnId; + label: string; }; - const COMPOSITIONS: CompositionMode[] = [ { type: Composition.And, - label: 'All conditions', + label: 'All conditions' }, { type: Composition.Or, - label: 'Any of the conditions', - }, + label: 'Any of the conditions' + } ]; - const FIELDS: Field[] = [ { id: IndexedColumnId.FullText, - label: 'Full text search', + label: 'Full text search' }, { id: IndexedColumnId.Owner, - label: 'Owner name', + label: 'Owner name' }, { id: IndexedColumnId.Path, - label: 'File name', + label: 'File name' }, { id: IndexedColumnId.Server, - label: 'Server URL', + label: 'Server URL' }, { id: IndexedColumnId.Cells, - label: 'Text in cell', + label: 'Text in cell' }, { id: IndexedColumnId.Outputs, - label: 'Output of cell', + label: 'Output of cell' }, { id: IndexedColumnId.CellMemes, - label: 'MEME of cell', - }, + label: 'MEME of cell' + } /* ['lc_notebook_meme__current', 'MEME of notebook'], ['signature_notebook_path', 'File path'], @@ -83,74 +85,87 @@ const FIELDS: Field[] = [ */ ]; - type FieldQuery = { - target: IndexedColumnId, + target: IndexedColumnId; query: string; }; - export type CompositeQuery = { - composition: Composition, - fields: FieldQuery[], + composition: Composition; + fields: FieldQuery[]; }; - export type FieldsQueryProps = { onChange?: (query: CompositeQuery) => void; }; - export function FieldsQuery(props: FieldsQueryProps): JSX.Element { const { onChange } = props; const [composition, setComposition] = useState(Composition.And); const [fieldQueries, setFieldQueries] = useState([ { target: IndexedColumnId.FullText, - query: '*', + query: '*' } ]); - const updateFieldQueriesTarget = useCallback((index: number, target: IndexedColumnId) => { - const newQueries: FieldQuery[] = fieldQueries.map((q) => Object.assign({}, q)); - newQueries[index].target = target; - setFieldQueries(newQueries); - if (!onChange) { - return; - } - onChange({ - composition, - fields: newQueries, - }); - }, [fieldQueries, composition]); - const updateFieldQueriesQuery = useCallback((index: number, value: string) => { - const newQueries: FieldQuery[] = fieldQueries.map((q) => Object.assign({}, q)); - newQueries[index].query = value; - setFieldQueries(newQueries); - if (!onChange) { - return; - } - onChange({ - composition, - fields: newQueries, - }); - }, [fieldQueries, composition]); - const deleteFieldQueries = useCallback((index: number) => { - const newQueries: FieldQuery[] = fieldQueries.map((q) => Object.assign({}, q)); - const removedQueries = newQueries.splice(index, 1); - setFieldQueries(removedQueries); - if (!onChange) { - return; - } - onChange({ - composition, - fields: removedQueries, - }); - }, [fieldQueries, composition]); + const updateFieldQueriesTarget = useCallback( + (index: number, target: IndexedColumnId) => { + const newQueries: FieldQuery[] = fieldQueries.map(q => + Object.assign({}, q) + ); + newQueries[index].target = target; + setFieldQueries(newQueries); + if (!onChange) { + return; + } + onChange({ + composition, + fields: newQueries + }); + }, + [fieldQueries, composition] + ); + const updateFieldQueriesQuery = useCallback( + (index: number, value: string) => { + const newQueries: FieldQuery[] = fieldQueries.map(q => + Object.assign({}, q) + ); + newQueries[index].query = value; + setFieldQueries(newQueries); + if (!onChange) { + return; + } + onChange({ + composition, + fields: newQueries + }); + }, + [fieldQueries, composition] + ); + const deleteFieldQueries = useCallback( + (index: number) => { + const newQueries: FieldQuery[] = fieldQueries.map(q => + Object.assign({}, q) + ); + const removedQueries = newQueries.splice(index, 1); + setFieldQueries(removedQueries); + if (!onChange) { + return; + } + onChange({ + composition, + fields: removedQueries + }); + }, + [fieldQueries, composition] + ); const addFieldQueries = useCallback(() => { - const newQueries: FieldQuery[] = fieldQueries.map((q) => Object.assign({}, q)); + const newQueries: FieldQuery[] = fieldQueries.map(q => + Object.assign({}, q) + ); newQueries.push({ target: IndexedColumnId.FullText, - query: '*', + query: '*' }); setFieldQueries(newQueries); if (!onChange) { @@ -158,70 +173,71 @@ export function FieldsQuery(props: FieldsQueryProps): JSX.Element { } onChange({ composition, - fields: newQueries, + fields: newQueries }); }, [fieldQueries, composition]); - const compositionChanged = useCallback((event: SelectChangeEvent) => { - const changed = event.target.value as Composition; - setComposition(changed); - if (!onChange) { - return; - } - onChange({ - composition: changed, - fields: fieldQueries, - }); - }, [fieldQueries]); - - return + const compositionChanged = useCallback( + (event: SelectChangeEvent) => { + const changed = event.target.value as Composition; + setComposition(changed); + if (!onChange) { + return; + } + onChange({ + composition: changed, + fields: fieldQueries + }); + }, + [fieldQueries] + ); + + return ( - are satisfied - - - {fieldQueries.map((query, index) => { - return - + {COMPOSITIONS.map(composition => ( + {composition.label} + ))} + {' '} + are satisfied + + + {fieldQueries.map((query, index) => { + return ( + + - ) => - updateFieldQueriesQuery(index, event.target.value) - } - /> - - - })} - + {FIELDS.map(field => ( + {field.label} + ))} + + + ) => updateFieldQueriesQuery(index, event.target.value)} + /> + + + ); + })} + + - ; -} \ No newline at end of file + ); +} diff --git a/src/components/page-control.tsx b/src/components/page-control.tsx index 7fb9c2f..721b2ae 100644 --- a/src/components/page-control.tsx +++ b/src/components/page-control.tsx @@ -5,48 +5,51 @@ import { Box, Link } from '@mui/material'; import ChevronLeftIcon from '@mui/icons-material/ChevronLeft'; import ChevronRightIcon from '@mui/icons-material/ChevronRight'; - export type PageQuery = { start: number; limit: number; -} - +}; export type PageControlProps = { start: number; limit: number; numFound: number; onPageChange?: (query: PageQuery) => void; -} - +}; export function PageControl(props: PageControlProps): JSX.Element { const { start, limit, numFound, onPageChange } = props; const pageNum = `${start}-${Math.min(start + limit, numFound)} / ${numFound}`; - return - {start > 0 && onPageChange && { - onPageChange({ - start: Math.max(0, start - limit), - limit, - }); - }} - > - - } - {pageNum} - {start + limit < numFound && onPageChange && { - onPageChange({ - start: Math.max(0, start + limit), - limit, - }); - }} - > - - } - -} \ No newline at end of file + return ( + + {start > 0 && onPageChange && ( + { + onPageChange({ + start: Math.max(0, start - limit), + limit + }); + }} + > + + + )} + {pageNum} + {start + limit < numFound && onPageChange && ( + { + onPageChange({ + start: Math.max(0, start + limit), + limit + }); + }} + > + + + )} + + ); +} diff --git a/src/components/page.tsx b/src/components/page.tsx index d9b0616..cfa87b2 100644 --- a/src/components/page.tsx +++ b/src/components/page.tsx @@ -3,31 +3,35 @@ import React, { ReactNode } from 'react'; import { PageControl, PageQuery } from './page-control'; - export type PageProps = { start?: number; limit?: number; numFound?: number; onPageChange?: (query: PageQuery) => void; - children: ReactNode, + children: ReactNode; }; - export function Page(props: PageProps) { const { start, limit, numFound, onPageChange, children } = props; - return - {start !== undefined && limit !== undefined && numFound !== undefined && } - {children} - {start !== undefined && limit !== undefined && numFound !== undefined && } - -} \ No newline at end of file + return ( + + {start !== undefined && limit !== undefined && numFound !== undefined && ( + + )} + {children} + {start !== undefined && limit !== undefined && numFound !== undefined && ( + + )} + + ); +} diff --git a/src/components/query.tsx b/src/components/query.tsx index 5d25be7..6f3931c 100644 --- a/src/components/query.tsx +++ b/src/components/query.tsx @@ -1,97 +1,95 @@ import React, { useCallback, useState } from 'react'; -import { - Box, - Tabs, - Tab, -} from '@mui/material'; +import { Box, Tabs, Tab } from '@mui/material'; -import { SolrQuery } from "./solr-query"; +import { SolrQuery } from './solr-query'; import { CompositeQuery, FieldsQuery } from './fields-query'; - enum TabIndex { Fields, - Solr, -}; - + Solr +} export type QueryProps = { onChange?: (query: string | null) => void; }; - type TabPanelProps = { children?: React.ReactNode; id: TabIndex; value: TabIndex; -} - +}; function TabPanel(props: TabPanelProps): JSX.Element { const { value, id, children } = props; - return + return ( + + ); } - export function Query(props: QueryProps): JSX.Element { const { onChange } = props; const [solrQuery, setSolrQuery] = useState('_text_: *'); const [tabIndex, setTabIndex] = useState(TabIndex.Fields); - const solrChanged = useCallback((query: string | null) => { - setSolrQuery(query || undefined); - if (!onChange) { - return; - } - onChange(query); - }, [onChange]); - const fieldsChanged = useCallback((query: CompositeQuery) => { - const solrQuery = query.fields - .map((field) => `${field.target}: ${field.query}`) - .join(` ${query.composition} `); - console.log('TEST', solrQuery); - setSolrQuery(solrQuery); - if (!onChange) { - return; - } - onChange(solrQuery); - }, [onChange]); + const solrChanged = useCallback( + (query: string | null) => { + setSolrQuery(query || undefined); + if (!onChange) { + return; + } + onChange(query); + }, + [onChange] + ); + const fieldsChanged = useCallback( + (query: CompositeQuery) => { + const solrQuery = query.fields + .map(field => `${field.target}: ${field.query}`) + .join(` ${query.composition} `); + console.log('TEST', solrQuery); + setSolrQuery(solrQuery); + if (!onChange) { + return; + } + onChange(solrQuery); + }, + [onChange] + ); - return - setTabIndex(tabIndex as TabIndex)} - > - - - - - - - - - - ; -} \ No newline at end of file + return ( + + + setTabIndex(tabIndex as TabIndex) + } + > + + + + + + + + + + + ); +} diff --git a/src/components/result.tsx b/src/components/result.tsx index 1cfed6e..ce1bc1d 100644 --- a/src/components/result.tsx +++ b/src/components/result.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { TableRow, TableCell, Link } from '@mui/material'; - export enum IndexedColumnId { FullText = '_text_', Cells = 'source', @@ -13,10 +12,9 @@ export enum IndexedColumnId { Modified = 'mtime', Executed = 'lc_cell_meme__execution_end_time', OperationNote = 'source__markdown__operation_note', - NumberOfHeaders = 'source__markdown__heading_count', + NumberOfHeaders = 'source__markdown__heading_count' } - export type ResultEntity = { id: string; atime?: string; @@ -38,12 +36,10 @@ export type ResultEntity = { source__markdown__url?: string; source__markdown__operation_note?: string; _version_: string; -} - +}; export type StoredColumnId = keyof ResultEntity; - export type ResultProps = { columns: StoredColumnId[]; data: ResultEntity; @@ -53,30 +49,27 @@ export type ResultProps = { function renderValue( data: ResultEntity, column: StoredColumnId, - onSelect?: (result: ResultEntity) => void, + onSelect?: (result: ResultEntity) => void ): JSX.Element { const value = data[column]; if (column === 'filename' && onSelect) { - return onSelect(data)} - > - {value} - + return ( + onSelect(data)}> + {value} + + ); } return
{value || ''}
; } export function Result(props: ResultProps) { - const { - columns, - data, - onSelect, - } = props; + const { columns, data, onSelect } = props; - return - {columns.map((column) => ( - {renderValue(data, column, onSelect)} - ))} - -} \ No newline at end of file + return ( + + {columns.map(column => ( + {renderValue(data, column, onSelect)} + ))} + + ); +} diff --git a/src/components/results.tsx b/src/components/results.tsx index fc3e7ff..8c50f4d 100644 --- a/src/components/results.tsx +++ b/src/components/results.tsx @@ -1,10 +1,22 @@ import React, { useState, useCallback } from 'react'; -import { Typography, Table, TableHead, TableBody, TableRow, TableCell, Link } from '@mui/material'; +import { + Typography, + Table, + TableHead, + TableBody, + TableRow, + TableCell, + Link +} from '@mui/material'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp'; -import { IndexedColumnId, StoredColumnId, ResultEntity, Result } from './result'; - +import { + IndexedColumnId, + StoredColumnId, + ResultEntity, + Result +} from './result'; type Column = { id: IndexedColumnId; @@ -12,131 +24,132 @@ type Column = { value: StoredColumnId; }; - export enum SortOrder { Ascending, - Descending, -}; - + Descending +} export type SortQuery = { column: IndexedColumnId; order: SortOrder; }; - const COLUMNS: Column[] = [ { id: IndexedColumnId.Path, label: 'Path', - value: 'filename', + value: 'filename' }, { id: IndexedColumnId.Server, label: 'Server', - value: 'signature_server_url', + value: 'signature_server_url' }, { id: IndexedColumnId.Owner, label: 'Owner', - value: 'owner', + value: 'owner' }, { id: IndexedColumnId.Modified, label: 'Modified', - value: 'mtime', + value: 'mtime' }, { id: IndexedColumnId.Executed, label: 'Executed', - value: 'lc_cell_meme__execution_end_time', + value: 'lc_cell_meme__execution_end_time' }, { id: IndexedColumnId.OperationNote, label: 'Operation Note', - value: 'source__markdown__operation_note', + value: 'source__markdown__operation_note' }, { id: IndexedColumnId.NumberOfHeaders, label: '# of Headers', - value: 'source__markdown__heading_count', - }, + value: 'source__markdown__heading_count' + } ]; - export type ResultsProps = { data?: ResultEntity[]; onColumnSort?: (key: SortQuery) => void; onResultSelect?: (data: ResultEntity) => void; }; - function renderColumn( column: Column, sortHandler: (key: SortQuery) => void, - sortQuery: SortQuery | null, + sortQuery: SortQuery | null ) { - return { - let order = SortOrder.Ascending; - if (sortQuery && sortQuery.column === column.id) { - if (sortQuery.order === SortOrder.Ascending) { - order = SortOrder.Descending; + return ( + { + let order = SortOrder.Ascending; + if (sortQuery && sortQuery.column === column.id) { + if (sortQuery.order === SortOrder.Ascending) { + order = SortOrder.Descending; + } } - } - sortHandler({ - column: column.id, - order, - }); - }} - > -
- {column.label} - {sortQuery?.column === column.id && sortQuery.order === SortOrder.Ascending && - } - {sortQuery?.column === column.id && sortQuery.order === SortOrder.Descending && - } -
- ; + sortHandler({ + column: column.id, + order + }); + }} + > +
+ {column.label} + {sortQuery?.column === column.id && + sortQuery.order === SortOrder.Ascending && } + {sortQuery?.column === column.id && + sortQuery.order === SortOrder.Descending && } +
+ + ); } - export function Results(props: ResultsProps) { const { data, onColumnSort, onResultSelect } = props; if (!data || data.length === 0) { - return - No results - + return No results; } const [sortQuery, setSortQuery] = useState(null); - const sorted = useCallback((key: SortQuery) => { - setSortQuery(key); - if (!onColumnSort) { - return; - } - onColumnSort(key); - }, [onColumnSort]) - - return - - - {COLUMNS.map((column) => ( - {renderColumn(column, sorted, sortQuery)} + const sorted = useCallback( + (key: SortQuery) => { + setSortQuery(key); + if (!onColumnSort) { + return; + } + onColumnSort(key); + }, + [onColumnSort] + ); + + return ( +
+ + + {COLUMNS.map(column => ( + {renderColumn(column, sorted, sortQuery)} + ))} + + + + {data.map(result => ( + c.value)} + data={result} + /> ))} - - - - {data.map((result) => ( - c.value)} - data={result} - /> - ))} - -
-} \ No newline at end of file + + + ); +} diff --git a/src/components/search.tsx b/src/components/search.tsx index 321f37d..afefbb5 100644 --- a/src/components/search.tsx +++ b/src/components/search.tsx @@ -7,11 +7,9 @@ import { Results, SortQuery } from './results'; import { Page } from './page'; import { PageQuery } from './page-control'; - export type SearchError = { message: string; -} - +}; export type SearchQuery = { queryString: string; @@ -19,7 +17,6 @@ export type SearchQuery = { pageQuery?: PageQuery; }; - export type SearchProps = { onSearch?: (query: SearchQuery) => void; onResultSelect?: (result: ResultEntity) => void; @@ -30,24 +27,26 @@ export type SearchProps = { error?: SearchError; }; - -function getSearchQuery(lastQuery: SearchQuery | null, queryString?: string): SearchQuery | null { +function getSearchQuery( + lastQuery: SearchQuery | null, + queryString?: string +): SearchQuery | null { if (!queryString) { return lastQuery; } if (!lastQuery) { return { - queryString: queryString || '', + queryString: queryString || '' }; } return Object.assign({}, lastQuery, { - queryString: queryString || '', + queryString: queryString || '' }); } - export function Search(props: SearchProps): JSX.Element { - const { onSearch, onResultSelect, start, limit, numFound, results, error } = props; + const { onSearch, onResultSelect, start, limit, numFound, results, error } = + props; const [solrQuery, setSolrQuery] = useState('_text_: *'); const [searchQuery, setSearchQuery] = useState(null); @@ -65,56 +64,61 @@ export function Search(props: SearchProps): JSX.Element { } onSearch(query); }, [solrQuery, onSearch]); - const sorted = useCallback((sortQuery: SortQuery) => { - const query = getSearchQuery(searchQuery); - if (query === null) { - return; - } - const newQuery: SearchQuery = Object.assign(query, { - sortQuery, - }); - setSearchQuery(newQuery); - if (!onSearch) { - return; - } - onSearch(newQuery); - }, [onSearch]); - const pageChanged = useCallback((pageQuery: PageQuery) => { - const query = getSearchQuery(searchQuery); - if (query === null) { - return; - } - const newQuery: SearchQuery = Object.assign(query, { - pageQuery, - }); - setSearchQuery(newQuery); - if (!onSearch) { - return; - } - onSearch(newQuery); - }, [onSearch]); - return - - - {error && {error.message}} - - - - - - ; -} \ No newline at end of file + const sorted = useCallback( + (sortQuery: SortQuery) => { + const query = getSearchQuery(searchQuery); + if (query === null) { + return; + } + const newQuery: SearchQuery = Object.assign(query, { + sortQuery + }); + setSearchQuery(newQuery); + if (!onSearch) { + return; + } + onSearch(newQuery); + }, + [onSearch] + ); + const pageChanged = useCallback( + (pageQuery: PageQuery) => { + const query = getSearchQuery(searchQuery); + if (query === null) { + return; + } + const newQuery: SearchQuery = Object.assign(query, { + pageQuery + }); + setSearchQuery(newQuery); + if (!onSearch) { + return; + } + onSearch(newQuery); + }, + [onSearch] + ); + return ( + + + + {error && {error.message}} + + + + + + + ); +} diff --git a/src/components/solr-query.tsx b/src/components/solr-query.tsx index 0ecd635..97852c5 100644 --- a/src/components/solr-query.tsx +++ b/src/components/solr-query.tsx @@ -1,35 +1,38 @@ import React, { ChangeEvent, useCallback } from 'react'; import { Box, TextField } from '@mui/material'; - export type SolrQueryProps = { query?: string; onChange?: (query: string | null) => void; }; - export function SolrQuery(props: SolrQueryProps): JSX.Element { const { query, onChange } = props; - const changed = useCallback((event: ChangeEvent) => { - if (!onChange) { - return; - } - const query = event.target.value.trim(); - if (!query) { - onChange(null); - return; - } - onChange(query); - }, [onChange]); - return - - ; -} \ No newline at end of file + const changed = useCallback( + (event: ChangeEvent) => { + if (!onChange) { + return; + } + const query = event.target.value.trim(); + if (!query) { + onChange(null); + return; + } + onChange(query); + }, + [onChange] + ); + return ( + + + + ); +} diff --git a/src/handler.ts b/src/handler.ts index 607d422..8627020 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -43,4 +43,4 @@ export async function requestAPI( } return data; -} \ No newline at end of file +} diff --git a/src/index.ts b/src/index.ts index ed9f214..3763b11 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,14 +9,13 @@ import { ISettingRegistry } from '@jupyterlab/settingregistry'; import { FilesInitializer } from './widgets/files-initializer'; import { buildWidget } from './widgets/search-widget'; - function initWidgets( app: JupyterFrontEnd, documents: IDocumentManager, - settings: ISettingRegistry.ISettings, + settings: ISettingRegistry.ISettings ) { - const initializer = new FilesInitializer( - (withLabel: boolean) => buildWidget(documents, withLabel), + const initializer = new FilesInitializer((withLabel: boolean) => + buildWidget(documents, withLabel) ); initializer.start(app); } @@ -32,7 +31,7 @@ const plugin: JupyterFrontEndPlugin = { activate: ( app: JupyterFrontEnd, settingRegistry: ISettingRegistry | null, - documents: IDocumentManager | null, + documents: IDocumentManager | null ) => { console.log('JupyterLab extension nbsearch is activated!'); if (settingRegistry) { diff --git a/src/widgets/files-initializer.ts b/src/widgets/files-initializer.ts index e54a80a..f9fab3b 100644 --- a/src/widgets/files-initializer.ts +++ b/src/widgets/files-initializer.ts @@ -1,10 +1,8 @@ import { JupyterFrontEnd } from '@jupyterlab/application'; import { Widget, TabPanel } from '@lumino/widgets'; - type WidgetFactory = (withLabel: boolean) => Widget; - export class FilesInitializer { widgetFactory: WidgetFactory; @@ -32,4 +30,4 @@ export class FilesInitializer { } tab.addWidget(this.widgetFactory(true)); } -} \ No newline at end of file +} diff --git a/src/widgets/icons.tsx b/src/widgets/icons.tsx index 6187010..ec5c48a 100644 --- a/src/widgets/icons.tsx +++ b/src/widgets/icons.tsx @@ -2,12 +2,10 @@ import { LabIcon } from '@jupyterlab/ui-components'; import { faMagnifyingGlass } from '@fortawesome/free-solid-svg-icons'; - type Icon = { icon: any[]; }; - function extractSvgString(icon: Icon): string { const path = icon.icon[4]; return ` @@ -17,8 +15,7 @@ function extractSvgString(icon: Icon): string { `; } - export const searchIcon = new LabIcon({ name: 'nbsearch::notebooksearch', - svgstr: extractSvgString(faMagnifyingGlass), -}); \ No newline at end of file + svgstr: extractSvgString(faMagnifyingGlass) +}); diff --git a/src/widgets/search-widget.tsx b/src/widgets/search-widget.tsx index d5a9707..3429d49 100644 --- a/src/widgets/search-widget.tsx +++ b/src/widgets/search-widget.tsx @@ -10,8 +10,6 @@ import { ResultEntity } from '../components/result'; import { requestAPI } from '../handler'; import { SortOrder } from '../components/results'; - - type SearchResponse = { notebooks: ResultEntity[]; limit: number; @@ -19,100 +17,106 @@ type SearchResponse = { numFound: number; }; - type NotebookResponse = { filename: string; }; - async function performSearch(query: SearchQuery): Promise { const params: { - query: string, - sort?: string, - limit?: string, - start?: string, + query: string; + sort?: string; + limit?: string; + start?: string; } = { - query: query.queryString, + query: query.queryString }; const { sortQuery, pageQuery } = query; if (sortQuery) { - params.sort = `${sortQuery.column} ${sortQuery.order === SortOrder.Ascending ? 'asc' : 'desc'}` + params.sort = `${sortQuery.column} ${ + sortQuery.order === SortOrder.Ascending ? 'asc' : 'desc' + }`; } if (pageQuery) { params.limit = pageQuery.limit.toString(); params.start = pageQuery.start.toString(); } const resp = await requestAPI( - `v1/notebook/search?${new URLSearchParams(params)}`, + `v1/notebook/search?${new URLSearchParams(params)}` ); return resp; } - -async function prepareNotebook(path: string, id: string): Promise { - const resp = await requestAPI( - `v1/import${path}/${id}`, - ); +async function prepareNotebook( + path: string, + id: string +): Promise { + const resp = await requestAPI(`v1/import${path}/${id}`); return resp; } - type SearchWidgetProps = { documents: IDocumentManager; -} - +}; export function SearchWidget(props: SearchWidgetProps): JSX.Element { const { documents } = props; const [results, setResults] = useState([]); const [page, setPage] = useState<{ - start: number, - limit: number, - numFound: number + start: number; + limit: number; + numFound: number; } | null>(null); const [error, setError] = useState(undefined); - const searched = useCallback((query: SearchQuery) => { - performSearch(query) - .then((results) => { - setError(undefined); - setResults(results.notebooks); - setPage({ - start: results.start, - limit: results.limit, - numFound: results.numFound, + const searched = useCallback( + (query: SearchQuery) => { + performSearch(query) + .then(results => { + setError(undefined); + setResults(results.notebooks); + setPage({ + start: results.start, + limit: results.limit, + numFound: results.numFound + }); + }) + .catch(error => { + setError(error); + }); + }, + [results] + ); + const selected = useCallback( + (result: ResultEntity) => { + prepareNotebook('/nbsearch-tmp', result.id) + .then(result => { + documents.openOrReveal(`/nbsearch-tmp/${result.filename}`); + }) + .catch(error => { + setError(error); }); - }) - .catch((error) => { - setError(error); - }); - }, [results]); - const selected = useCallback((result: ResultEntity) => { - prepareNotebook('/nbsearch-tmp', result.id) - .then((result) => { - documents.openOrReveal(`/nbsearch-tmp/${result.filename}`); - }) - .catch((error) => { - setError(error); - }); - }, [documents]); - return - - + }, + [documents] + ); + return ( + + + + ); } - -export function buildWidget(documents: IDocumentManager, withLabel: boolean): ReactWidget { - const widget = ReactWidget.create( - - ); +export function buildWidget( + documents: IDocumentManager, + withLabel: boolean +): ReactWidget { + const widget = ReactWidget.create(); widget.id = 'nbsearch::notebooksearch'; widget.title.icon = searchIcon; widget.title.caption = 'NBSearch'; @@ -120,4 +124,4 @@ export function buildWidget(documents: IDocumentManager, withLabel: boolean): Re widget.title.label = 'NBSearch'; } return widget; -} \ No newline at end of file +}