Skip to content

Commit

Permalink
Support for searching for previous event in the Events Table
Browse files Browse the repository at this point in the history
- Add a 'previous' button in the column search cells right beside the
'next' button
- Use keyboard short-cut SHIFT+ENTER to search previous event

fixes #412

Signed-off-by: Bernd Hufmann <Bernd.Hufmann@ericsson.com>
Signed-off-by: Patrick Tasse <patrick.tasse@ericsson.com>
  • Loading branch information
bhufmann authored and PatrickTasse committed Aug 11, 2021
1 parent cb7d812 commit fe0833d
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 17 deletions.
87 changes: 72 additions & 15 deletions packages/react-components/src/components/table-output-component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ type TableOutputProps = AbstractOutputProps & {
tableWidth?: string;
};

enum Direction {
NEXT,
PREVIOUS
}

export class TableOutputComponent extends AbstractOutputComponent<TableOutputProps, TableOuputState> {
private debugMode = false;
private columnIds: Array<number> = [];
Expand Down Expand Up @@ -83,7 +88,7 @@ export class TableOutputComponent extends AbstractOutputComponent<TableOutputPro
this.onModelUpdated = this.onModelUpdated.bind(this);
this.onKeyDown = this.onKeyDown.bind(this);
this.searchEvents = this.searchEvents.bind(this);
this.findNextMatchedEvent = this.findNextMatchedEvent.bind(this);
this.findMatchedEvent = this.findMatchedEvent.bind(this);
}

renderMainArea(): React.ReactNode {
Expand Down Expand Up @@ -314,7 +319,8 @@ export class TableOutputComponent extends AbstractOutputComponent<TableOutputPro
floatingFilterComponentParams: {
suppressFilterButton: true,
onFilterChange: this.searchEvents,
onclickNext: this.findNextMatchedEvent,
onclickNext: () => this.findMatchedEvent(Direction.NEXT),
onclickPrevious: () => this.findMatchedEvent(Direction.PREVIOUS),
colName: columnHeader.id.toString()
},
icons: {
Expand Down Expand Up @@ -409,7 +415,7 @@ export class TableOutputComponent extends AbstractOutputComponent<TableOutputPro
return lines[0].index;
}

private fetchAdditionalParams(isFiltered = false): ({ [key: string]: any }) {
private fetchAdditionalParams(direction?: Direction): ({ [key: string]: any }) {
let additionalParams: { [key: string]: any } = {};
const filterObj: { [key: number]: string } = {};
if (this.filterModel) {
Expand All @@ -419,8 +425,10 @@ export class TableOutputComponent extends AbstractOutputComponent<TableOutputPro
});
additionalParams = {
['table_search_expressions']: filterObj,
['isFiltered']: isFiltered
};
if (direction !== undefined) {
additionalParams['table_search_direction'] = Direction[direction];
}
}
return additionalParams;

Expand Down Expand Up @@ -490,11 +498,11 @@ export class TableOutputComponent extends AbstractOutputComponent<TableOutputPro
}
}

private async findNextMatchIndex(currRowIndex: number) {
private async findMatchIndex(currRowIndex: number, direction = Direction.NEXT) {
const traceUUID = this.props.traceId;
const tspClient = this.props.tspClient;
const outputId = this.props.outputDescriptor.id;
const additionalParams = this.fetchAdditionalParams(true);
const additionalParams = this.fetchAdditionalParams(direction);
const tspClientResponse = await tspClient.fetchTableLines(traceUUID, outputId, QueryHelper.tableQuery(this.columnIds, currRowIndex, 1, additionalParams));
const lineResponse = tspClientResponse.getModel();
if (!tspClientResponse.isOk() || !lineResponse) {
Expand All @@ -508,13 +516,56 @@ export class TableOutputComponent extends AbstractOutputComponent<TableOutputPro
return lines[0].index;
}

private async findNextMatchedEvent() {
private async findMatchedEvent(direction: Direction) {
let isFound = false;
if (this.gridApi) {
this.gridApi.deselectAll();

// make sure that both index are either both -1 or both have a valid number
if (this.selectStartIndex !== -1 && this.selectEndIndex === -1) {
this.selectEndIndex = this.selectStartIndex;
}
if (this.selectEndIndex !== -1 && this.selectStartIndex === -1) {
this.selectStartIndex = this.selectStartIndex;
}

let currRowIndex = 0;
if (this.selectStartIndex !== -1) {
if (direction === Direction.NEXT) {
currRowIndex = Math.max(this.selectStartIndex, this.selectEndIndex) + 1;
} else {
currRowIndex = Math.min(this.selectStartIndex, this.selectEndIndex) - 1;
}
} else if (direction === Direction.PREVIOUS) {
// no backward search if there is no selection
return;
}

let rowNodes: RowNode[] = [];
this.gridApi.forEachNode(rowNode => {
if (rowNode.rowIndex > Math.max(this.selectStartIndex, this.selectEndIndex) && rowNode.data
&& rowNode.data['isMatched'] && !isFound) {
rowNodes.push(rowNode);
});

if (direction === Direction.PREVIOUS) {
rowNodes = rowNodes.reverse();
}

this.gridApi.deselectAll();
// consider only rows starting from the current row index and contiguous rows after that
let currRowIndexFound = false;
rowNodes.forEach(rowNode => {
if (rowNode.rowIndex === currRowIndex) {
currRowIndexFound = true;
// update current row index to next/previous contiguous row
if (direction === Direction.NEXT) {
currRowIndex++;
} else {
currRowIndex--;
}
} else {
// non-contiguous row found, stop searching in cache
currRowIndexFound = false;
}
if (currRowIndexFound && !isFound && rowNode.data && rowNode.data['isMatched']) {
this.gridApi?.ensureIndexVisible(rowNode.rowIndex);
this.selectStartIndex = this.selectEndIndex = rowNode.rowIndex;
this.handleRowSelectionChange();
Expand All @@ -524,14 +575,20 @@ export class TableOutputComponent extends AbstractOutputComponent<TableOutputPro
});

if (isFound) {
// match found in cache
return;
}
// find match outside the cache
if (currRowIndex >= 0) {
const lineIndex = await this.findMatchIndex(currRowIndex, direction);
if (lineIndex !== undefined) {
this.gridApi.ensureIndexVisible(lineIndex);
this.selectStartIndex = this.selectEndIndex = lineIndex;
}
}

const currRowIndex = this.gridApi?.getLastDisplayedRow() + 1;
const lineIndex = await this.findNextMatchIndex(currRowIndex);
if (lineIndex) {
this.gridApi.ensureIndexVisible(lineIndex);
this.selectStartIndex = this.selectEndIndex = lineIndex;
// apply new or previous selection
if (this.selectStartIndex !== -1 && this.selectEndIndex !== -1) {
this.handleRowSelectionChange();
this.enableIndexSelection = true;
this.selectRows();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { faAngleDown, faSearch, faSpinner, faTimes } from '@fortawesome/free-solid-svg-icons';
import { faAngleDown, faAngleUp, faSearch, faSpinner, faTimes } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { ICellRendererParams, IFloatingFilterParams } from 'ag-grid-community';
import debounce from 'lodash.debounce';
Expand All @@ -12,6 +12,7 @@ type CellRendererProps = ICellRendererParams & {
type SearchFilterRendererProps = IFloatingFilterParams & {
onFilterChange: (colName: string, filterValue: string) => void;
onclickNext: () => void;
onclickPrevious: () => void;
colName: string;
};

Expand Down Expand Up @@ -90,6 +91,7 @@ export class SearchFilterRenderer extends React.Component<SearchFilterRendererPr
this.onMouseLeaveHandler = this.onMouseLeaveHandler.bind(this);
this.onClickHandler = this.onClickHandler.bind(this);
this.onDownClickHandler = this.onDownClickHandler.bind(this);
this.onUpClickHandler = this.onUpClickHandler.bind(this);
this.onCloseClickHandler = this.onCloseClickHandler.bind(this);
this.onKeyDownEvent = this.onKeyDownEvent.bind(this);

Expand All @@ -110,14 +112,19 @@ export class SearchFilterRenderer extends React.Component<SearchFilterRendererPr
<input type="text" autoFocus={true} onKeyDown={this.onKeyDownEvent} onInput={this.onInputBoxChanged} style={{ width: '50%', margin: '10px' }} />
<FontAwesomeIcon className='hoverClass' icon={faTimes} style={{ marginTop: '20px' }} onClick={this.onCloseClickHandler} />
<FontAwesomeIcon className='hoverClass' icon={faAngleDown} style={{ marginLeft: '10px', marginTop: '20px' }} onClick={this.onDownClickHandler} />
<FontAwesomeIcon className='hoverClass' icon={faAngleUp} style={{ marginLeft: '10px', marginTop: '20px' }} onClick={this.onUpClickHandler} />
</div>}
</div>
);
}

private onKeyDownEvent(event: React.KeyboardEvent) {
if (event.key === 'Enter') {
this.props.onclickNext();
if (event.shiftKey) {
this.props.onclickPrevious();
} else {
this.props.onclickNext();
}
} else if (event.key === 'Escape') {
this.setState({
hasClicked: false
Expand Down Expand Up @@ -158,6 +165,11 @@ export class SearchFilterRenderer extends React.Component<SearchFilterRendererPr
return;
}

private onUpClickHandler() {
this.props.onclickPrevious();
return;
}

private onCloseClickHandler(event: React.MouseEvent) {
this.setState({
hasClicked: false
Expand Down

0 comments on commit fe0833d

Please sign in to comment.