Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added global search on table panel #5893

Merged
merged 9 commits into from
Sep 20, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
box-sizing: border-box;
margin: 16px 0;
border-radius: 3px;

.global-search {
.ant-input-group-addon {
border: none;
background-color: var(--bg-ink-300);
}
}
}

.height-widget {
Expand Down Expand Up @@ -55,3 +62,15 @@
}
}
}

.lightMode {
.full-view-container {
.graph-container {
.global-search {
.ant-input-group-addon {
background-color: var(--bg-vanilla-200);
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import './WidgetFullView.styles.scss';

import { LoadingOutlined, SyncOutlined } from '@ant-design/icons';
import { Button, Spin } from 'antd';
import {
LoadingOutlined,
SearchOutlined,
SyncOutlined,
} from '@ant-design/icons';
import { Button, Input, Spin } from 'antd';
import cx from 'classnames';
import { ToggleGraphProps } from 'components/Graph/types';
import Spinner from 'components/Spinner';
Expand Down Expand Up @@ -172,6 +176,10 @@ function FullView({

const isListView = widget.panelTypes === PANEL_TYPES.LIST;

const isTablePanel = widget.panelTypes === PANEL_TYPES.TABLE;

const [searchTerm, setSearchTerm] = useState<string>('');

if (response.isLoading && widget.panelTypes !== PANEL_TYPES.LIST) {
return <Spinner height="100%" size="large" tip="Loading..." />;
}
Expand Down Expand Up @@ -216,6 +224,18 @@ function FullView({
}}
isGraphLegendToggleAvailable={canModifyChart}
>
{isTablePanel && (
<Input
addonBefore={<SearchOutlined size={14} />}
className="global-search"
placeholder="Search..."
allowClear
key={widget.id}
onChange={(e): void => {
setSearchTerm(e.target.value || '');
}}
/>
)}
<PanelWrapper
queryResponse={response}
widget={widget}
Expand All @@ -226,6 +246,7 @@ function FullView({
graphVisibility={graphsVisibilityStates}
onDragSelect={onDragSelect}
tableProcessedDataRef={tableProcessedDataRef}
searchTerm={searchTerm}
/>
</GraphContainer>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ function WidgetGraphComponent({
});
};

const [searchTerm, setSearchTerm] = useState<string>('');

const loadingState =
(queryResponse.isLoading || queryResponse.status === 'idle') &&
widget.panelTypes !== PANEL_TYPES.LIST;
Expand Down Expand Up @@ -317,6 +319,7 @@ function WidgetGraphComponent({
isWarning={isWarning}
isFetchingResponse={isFetchingResponse}
tableProcessedDataRef={tableProcessedDataRef}
setSearchTerm={setSearchTerm}
/>
</div>
{queryResponse.isLoading && widget.panelTypes !== PANEL_TYPES.LIST && (
Expand All @@ -337,6 +340,7 @@ function WidgetGraphComponent({
onDragSelect={onDragSelect}
tableProcessedDataRef={tableProcessedDataRef}
customTooltipElement={customTooltipElement}
searchTerm={searchTerm}
/>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,22 @@
display: flex;
justify-content: space-between;
align-items: center;
height: 30px;
height: 36px;
width: 100%;
padding: 0.5rem;
box-sizing: border-box;
font-size: 14px;
font-weight: 600;

cursor: move;

.ant-input-group-addon {
border: none;
background-color: var(--bg-ink-500);
}
.search-header-icons {
cursor: pointer;
}
}

.widget-header-title {
Expand All @@ -19,6 +27,7 @@
.widget-header-actions {
display: flex;
align-items: center;
gap: 8px;
}
.widget-header-more-options {
visibility: hidden;
Expand All @@ -30,10 +39,22 @@
padding: 8px;
}

.widget-header-more-options-visible {
visibility: visible;
}

.widget-header-hover {
visibility: visible;
}

.widget-api-actions {
padding-right: 0.25rem;
}

.lightMode {
.widget-header-container {
.ant-input-group-addon {
background-color: inherit;
}
}
}
124 changes: 83 additions & 41 deletions frontend/src/container/GridCardLayout/WidgetHeader/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import {
ExclamationCircleOutlined,
FullscreenOutlined,
MoreOutlined,
SearchOutlined,
WarningOutlined,
} from '@ant-design/icons';
import { Dropdown, MenuProps, Tooltip, Typography } from 'antd';
import { Dropdown, Input, MenuProps, Tooltip, Typography } from 'antd';
import Spinner from 'components/Spinner';
import { QueryParams } from 'constants/query';
import { PANEL_TYPES } from 'constants/queryBuilder';
Expand All @@ -20,8 +21,9 @@ import useComponentPermission from 'hooks/useComponentPermission';
import history from 'lib/history';
import { RowData } from 'lib/query/createTableColumnsFromQuery';
import { isEmpty } from 'lodash-es';
import { X } from 'lucide-react';
import { unparse } from 'papaparse';
import { ReactNode, useCallback, useMemo } from 'react';
import { ReactNode, useCallback, useMemo, useState } from 'react';
import { UseQueryResult } from 'react-query';
import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers';
Expand Down Expand Up @@ -51,6 +53,7 @@ interface IWidgetHeaderProps {
isWarning: boolean;
isFetchingResponse: boolean;
tableProcessedDataRef: React.MutableRefObject<RowData[]>;
setSearchTerm: React.Dispatch<React.SetStateAction<string>>;
}

function WidgetHeader({
Expand All @@ -67,6 +70,7 @@ function WidgetHeader({
isWarning,
isFetchingResponse,
tableProcessedDataRef,
setSearchTerm,
}: IWidgetHeaderProps): JSX.Element | null {
const onEditHandler = useCallback((): void => {
const widgetId = widget.id;
Expand Down Expand Up @@ -187,6 +191,10 @@ function WidgetHeader({

const updatedMenuList = useMemo(() => generateMenuList(actions), [actions]);

const [showGlobalSearch, setShowGlobalSearch] = useState(false);

const globalSearchAvailable = widget.panelTypes === PANEL_TYPES.TABLE;

const menu = useMemo(
() => ({
items: updatedMenuList,
Expand All @@ -201,46 +209,80 @@ function WidgetHeader({

return (
<div className="widget-header-container">
<Typography.Text
ellipsis
data-testid={title}
className="widget-header-title"
>
{title}
</Typography.Text>
<div className="widget-header-actions">
<div className="widget-api-actions">{threshold}</div>
{isFetchingResponse && !queryResponse.isError && (
<Spinner style={{ paddingRight: '0.25rem' }} />
)}
{queryResponse.isError && (
<Tooltip
title={errorMessage}
placement={errorTooltipPosition}
className="widget-api-actions"
{showGlobalSearch ? (
<Input
addonBefore={<SearchOutlined size={14} />}
placeholder="Search..."
bordered={false}
data-testid="widget-header-search-input"
autoFocus
addonAfter={
<X
size={14}
onClick={(e): void => {
e.stopPropagation();
e.preventDefault();
setShowGlobalSearch(false);
}}
className="search-header-icons"
/>
}
key={widget.id}
onChange={(e): void => {
setSearchTerm(e.target.value || '');
}}
/>
) : (
<>
<Typography.Text
ellipsis
data-testid={title}
className="widget-header-title"
>
<ExclamationCircleOutlined />
</Tooltip>
)}

{isWarning && (
<Tooltip
title={WARNING_MESSAGE}
placement={errorTooltipPosition}
className="widget-api-actions"
>
<WarningOutlined />
</Tooltip>
)}
<Dropdown menu={menu} trigger={['hover']} placement="bottomRight">
<MoreOutlined
data-testid="widget-header-options"
className={`widget-header-more-options ${
parentHover ? 'widget-header-hover' : ''
}`}
/>
</Dropdown>
</div>
{title}
</Typography.Text>
<div className="widget-header-actions">
<div className="widget-api-actions">{threshold}</div>
{isFetchingResponse && !queryResponse.isError && (
<Spinner style={{ paddingRight: '0.25rem' }} />
)}
{queryResponse.isError && (
<Tooltip
title={errorMessage}
placement={errorTooltipPosition}
className="widget-api-actions"
>
<ExclamationCircleOutlined />
</Tooltip>
)}

{isWarning && (
<Tooltip
title={WARNING_MESSAGE}
placement={errorTooltipPosition}
className="widget-api-actions"
>
<WarningOutlined />
</Tooltip>
)}
{globalSearchAvailable && (
<SearchOutlined
className="search-header-icons"
onClick={(): void => setShowGlobalSearch(true)}
data-testid="widget-header-search"
/>
)}
<Dropdown menu={menu} trigger={['hover']} placement="bottomRight">
<MoreOutlined
data-testid="widget-header-options"
className={`widget-header-more-options ${
parentHover ? 'widget-header-hover' : ''
} ${globalSearchAvailable ? 'widget-header-more-options-visible' : ''}`}
/>
</Dropdown>
</div>
</>
)}
</div>
);
}
Expand Down
1 change: 1 addition & 0 deletions frontend/src/container/GridTableComponent/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export type GridTableComponentProps = {
columnUnits?: ColumnUnit;
tableProcessedDataRef?: React.MutableRefObject<RowData[]>;
sticky?: TableProps<RowData>['sticky'];
searchTerm?: string;
} & Pick<LogsExplorerTableProps, 'data'> &
Omit<TableProps<RowData>, 'columns' | 'dataSource'>;

Expand Down
2 changes: 2 additions & 0 deletions frontend/src/container/PanelWrapper/PanelWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ function PanelWrapper({
selectedGraph,
tableProcessedDataRef,
customTooltipElement,
searchTerm,
}: PanelWrapperProps): JSX.Element {
const Component = PanelTypeVsPanelWrapper[
selectedGraph || widget.panelTypes
Expand All @@ -39,6 +40,7 @@ function PanelWrapper({
selectedGraph={selectedGraph}
tableProcessedDataRef={tableProcessedDataRef}
customTooltipElement={customTooltipElement}
searchTerm={searchTerm}
/>
);
}
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/container/PanelWrapper/TablePanelWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ function TablePanelWrapper({
widget,
queryResponse,
tableProcessedDataRef,
searchTerm,
}: PanelWrapperProps): JSX.Element {
const panelData =
(queryResponse.data?.payload?.data?.result?.[0] as any)?.table || [];
Expand All @@ -20,6 +21,7 @@ function TablePanelWrapper({
columnUnits={widget.columnUnits}
tableProcessedDataRef={tableProcessedDataRef}
sticky={widget.panelTypes === PANEL_TYPES.TABLE}
searchTerm={searchTerm}
// eslint-disable-next-line react/jsx-props-no-spreading
{...GRID_TABLE_CONFIG}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export type PanelWrapperProps = {
onDragSelect: (start: number, end: number) => void;
selectedGraph?: PANEL_TYPES;
tableProcessedDataRef?: React.MutableRefObject<RowData[]>;
searchTerm?: string;
customTooltipElement?: HTMLDivElement;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ export type QueryTableProps = Omit<
columns?: ColumnsType<RowData>;
dataSource?: RowData[];
sticky?: TableProps<RowData>['sticky'];
searchTerm?: string;
};
Loading
Loading