mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-23 02:17:11 +00:00
feat: update explorer views
This commit is contained in:
parent
6deb75ff46
commit
bde078472b
@ -1,5 +0,0 @@
|
|||||||
.logs-qb {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
@ -1,79 +0,0 @@
|
|||||||
import './LogsQB.styles.scss';
|
|
||||||
|
|
||||||
import { ENTITY_VERSION_V4 } from 'constants/app';
|
|
||||||
import { Formula } from 'container/QueryBuilder/components/Formula/Formula';
|
|
||||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
|
||||||
import { memo } from 'react';
|
|
||||||
import { DataSource } from 'types/common/queryBuilder';
|
|
||||||
|
|
||||||
import { QueryBuilderV2Props } from '../QueryBuilderV2';
|
|
||||||
import QueryFooter from '../QueryV2/QueryFooter/QueryFooter';
|
|
||||||
import { QueryV2 } from '../QueryV2/QueryV2';
|
|
||||||
|
|
||||||
export const LogsQB = memo(function LogsQB({
|
|
||||||
filterConfigs,
|
|
||||||
}: QueryBuilderV2Props): JSX.Element {
|
|
||||||
const version = ENTITY_VERSION_V4;
|
|
||||||
|
|
||||||
const { currentQuery, addNewFormula, addNewBuilderQuery } = useQueryBuilder();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="logs-qb">
|
|
||||||
<div className="qb-content-container">
|
|
||||||
{currentQuery.builder.queryData.map((query, index) => (
|
|
||||||
<QueryV2
|
|
||||||
key={query.queryName}
|
|
||||||
index={index}
|
|
||||||
query={query}
|
|
||||||
filterConfigs={filterConfigs}
|
|
||||||
version={version}
|
|
||||||
isAvailableToDisable={false}
|
|
||||||
queryVariant="static"
|
|
||||||
source={DataSource.LOGS}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{currentQuery.builder.queryFormulas.length > 0 && (
|
|
||||||
<div className="qb-formulas-container">
|
|
||||||
{currentQuery.builder.queryFormulas.map((formula, index) => {
|
|
||||||
const query =
|
|
||||||
currentQuery.builder.queryData[index] ||
|
|
||||||
currentQuery.builder.queryData[0];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div key={formula.queryName} className="qb-formula">
|
|
||||||
<Formula
|
|
||||||
filterConfigs={filterConfigs}
|
|
||||||
query={query}
|
|
||||||
formula={formula}
|
|
||||||
index={index}
|
|
||||||
isAdditionalFilterEnable={false}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<QueryFooter
|
|
||||||
addNewBuilderQuery={addNewBuilderQuery}
|
|
||||||
addNewFormula={addNewFormula}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="query-names-section">
|
|
||||||
{currentQuery.builder.queryData.map((query) => (
|
|
||||||
<div key={query.queryName} className="query-name">
|
|
||||||
{query.queryName}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{currentQuery.builder.queryFormulas.map((formula) => (
|
|
||||||
<div key={formula.queryName} className="formula-name">
|
|
||||||
{formula.queryName}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
.metrics-qb {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 8px;
|
|
||||||
|
|
||||||
border-bottom: 1px solid var(--Slate-400, #1d212d);
|
|
||||||
|
|
||||||
.query-v2 {
|
|
||||||
.qb-entity-options {
|
|
||||||
.options {
|
|
||||||
.query-name {
|
|
||||||
&::before {
|
|
||||||
height: 306px !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,89 +0,0 @@
|
|||||||
import './MetricsQB.styles.scss';
|
|
||||||
|
|
||||||
import { ENTITY_VERSION_V4 } from 'constants/app';
|
|
||||||
import { Formula } from 'container/QueryBuilder/components/Formula/Formula';
|
|
||||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
|
||||||
import { useQueryOperations } from 'hooks/queryBuilder/useQueryBuilderOperations';
|
|
||||||
import { DataSource } from 'types/common/queryBuilder';
|
|
||||||
|
|
||||||
import { QueryBuilderV2Props } from '../QueryBuilderV2';
|
|
||||||
import QueryFooter from '../QueryV2/QueryFooter/QueryFooter';
|
|
||||||
import { QueryV2 } from '../QueryV2/QueryV2';
|
|
||||||
|
|
||||||
function MetricsQB({ filterConfigs }: QueryBuilderV2Props): JSX.Element {
|
|
||||||
const version = ENTITY_VERSION_V4;
|
|
||||||
|
|
||||||
const { currentQuery, addNewFormula, addNewBuilderQuery } = useQueryBuilder();
|
|
||||||
|
|
||||||
const { isMetricsDataSource } = useQueryOperations({
|
|
||||||
index: 0,
|
|
||||||
query: currentQuery.builder.queryData[0],
|
|
||||||
filterConfigs,
|
|
||||||
isListViewPanel: false,
|
|
||||||
entityVersion: version,
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('isMetricsDataSource', isMetricsDataSource);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="metrics-qb">
|
|
||||||
<div className="qb-content-container">
|
|
||||||
{currentQuery.builder.queryData.map((query, index) => (
|
|
||||||
<QueryV2
|
|
||||||
key={query.queryName}
|
|
||||||
index={index}
|
|
||||||
query={query}
|
|
||||||
filterConfigs={filterConfigs}
|
|
||||||
version={version}
|
|
||||||
isAvailableToDisable={false}
|
|
||||||
queryVariant="static"
|
|
||||||
source={DataSource.METRICS}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{currentQuery.builder.queryFormulas.length > 0 && (
|
|
||||||
<div className="qb-formulas-container">
|
|
||||||
{currentQuery.builder.queryFormulas.map((formula, index) => {
|
|
||||||
const query =
|
|
||||||
currentQuery.builder.queryData[index] ||
|
|
||||||
currentQuery.builder.queryData[0];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div key={formula.queryName} className="qb-formula">
|
|
||||||
<Formula
|
|
||||||
filterConfigs={filterConfigs}
|
|
||||||
query={query}
|
|
||||||
formula={formula}
|
|
||||||
index={index}
|
|
||||||
isAdditionalFilterEnable={false} // TODO: Need to enable this
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<QueryFooter
|
|
||||||
addNewBuilderQuery={addNewBuilderQuery}
|
|
||||||
addNewFormula={addNewFormula}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="query-names-section">
|
|
||||||
{currentQuery.builder.queryData.map((query) => (
|
|
||||||
<div key={query.queryName} className="query-name">
|
|
||||||
{query.queryName}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{currentQuery.builder.queryFormulas.map((formula) => (
|
|
||||||
<div key={formula.queryName} className="formula-name">
|
|
||||||
{formula.queryName}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default MetricsQB;
|
|
||||||
@ -1,13 +1,10 @@
|
|||||||
.query-builder-v2 {
|
.query-builder-v2 {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: row;
|
||||||
gap: 1rem;
|
gap: 4px;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 4px;
|
|
||||||
font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||||
'Helvetica Neue', sans-serif;
|
'Helvetica Neue', sans-serif;
|
||||||
|
|
||||||
@ -160,6 +157,7 @@
|
|||||||
|
|
||||||
margin-left: 32px;
|
margin-left: 32px;
|
||||||
padding-bottom: 16px;
|
padding-bottom: 16px;
|
||||||
|
padding-left: 8px;
|
||||||
|
|
||||||
.qb-formula {
|
.qb-formula {
|
||||||
.ant-row {
|
.ant-row {
|
||||||
@ -343,6 +341,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.query-data-source {
|
||||||
|
margin-left: 8px;
|
||||||
|
|
||||||
|
.ant-select-selector {
|
||||||
|
min-width: 120px;
|
||||||
|
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 1px solid var(--Slate-400, #1d212d);
|
||||||
|
background: var(--Ink-300, #16181d);
|
||||||
|
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.qb-search-container {
|
.qb-search-container {
|
||||||
|
|||||||
@ -1,108 +1,119 @@
|
|||||||
import './QueryBuilderV2.styles.scss';
|
import './QueryBuilderV2.styles.scss';
|
||||||
|
|
||||||
import { OPERATORS, PANEL_TYPES } from 'constants/queryBuilder';
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
|
import { Formula } from 'container/QueryBuilder/components/Formula';
|
||||||
import { QueryBuilderProps } from 'container/QueryBuilder/QueryBuilder.interfaces';
|
import { QueryBuilderProps } from 'container/QueryBuilder/QueryBuilder.interfaces';
|
||||||
import { memo, useMemo } from 'react';
|
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||||
|
import { memo, useEffect, useMemo } from 'react';
|
||||||
import { DataSource } from 'types/common/queryBuilder';
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
|
|
||||||
import { LogsQB } from './Logs/LogsQB';
|
|
||||||
import MetricsQB from './Metrics/MetricsQB';
|
|
||||||
import { QueryBuilderV2Provider } from './QueryBuilderV2Context';
|
import { QueryBuilderV2Provider } from './QueryBuilderV2Context';
|
||||||
import TracesQB from './Traces/TracesQB';
|
import QueryFooter from './QueryV2/QueryFooter/QueryFooter';
|
||||||
|
import { QueryV2 } from './QueryV2/QueryV2';
|
||||||
|
|
||||||
export type QueryBuilderV2Props = {
|
export const QueryBuilderV2 = memo(function QueryBuilderV2({
|
||||||
source: DataSource;
|
config,
|
||||||
panelType: PANEL_TYPES;
|
panelType: newPanelType,
|
||||||
filterConfigs: QueryBuilderProps['filterConfigs'];
|
filterConfigs = {},
|
||||||
isListViewPanel: boolean;
|
queryComponents,
|
||||||
version: string;
|
isListViewPanel = false,
|
||||||
};
|
showFunctions = false,
|
||||||
|
|
||||||
const QueryBuilderV2Main = memo(function QueryBuilderV2Main({
|
|
||||||
source,
|
|
||||||
panelType,
|
|
||||||
filterConfigs,
|
|
||||||
isListViewPanel,
|
|
||||||
version,
|
version,
|
||||||
}: QueryBuilderV2Props): JSX.Element {
|
}: QueryBuilderProps): JSX.Element {
|
||||||
const isMetricsDataSource = source === DataSource.METRICS;
|
const {
|
||||||
const isLogsDataSource = source === DataSource.LOGS;
|
currentQuery,
|
||||||
const isTracesDataSource = source === DataSource.TRACES;
|
addNewBuilderQuery,
|
||||||
|
addNewFormula,
|
||||||
|
handleSetConfig,
|
||||||
|
panelType,
|
||||||
|
initialDataSource,
|
||||||
|
} = useQueryBuilder();
|
||||||
|
|
||||||
const listViewLogFilterConfigs: QueryBuilderProps['filterConfigs'] = useMemo(() => {
|
console.log('isListViewPanel', isListViewPanel, showFunctions);
|
||||||
const config: QueryBuilderProps['filterConfigs'] = {
|
|
||||||
stepInterval: { isHidden: true, isDisabled: true },
|
|
||||||
having: { isHidden: true, isDisabled: true },
|
|
||||||
filters: {
|
|
||||||
customKey: 'body',
|
|
||||||
customOp: OPERATORS.CONTAINS,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return config;
|
const currentDataSource = useMemo(
|
||||||
}, []);
|
() =>
|
||||||
|
(config && config.queryVariant === 'static' && config.initialDataSource) ||
|
||||||
const listViewTracesFilterConfigs: QueryBuilderProps['filterConfigs'] = useMemo(() => {
|
null,
|
||||||
const config: QueryBuilderProps['filterConfigs'] = {
|
[config],
|
||||||
stepInterval: { isHidden: true, isDisabled: true },
|
|
||||||
having: { isHidden: true, isDisabled: true },
|
|
||||||
limit: { isHidden: true, isDisabled: true },
|
|
||||||
filters: {
|
|
||||||
customKey: 'body',
|
|
||||||
customOp: OPERATORS.CONTAINS,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return config;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="query-builder-v2">
|
|
||||||
{isMetricsDataSource ? (
|
|
||||||
<MetricsQB
|
|
||||||
source={DataSource.METRICS}
|
|
||||||
filterConfigs={filterConfigs}
|
|
||||||
panelType={panelType}
|
|
||||||
version={version}
|
|
||||||
isListViewPanel={isListViewPanel}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
{isLogsDataSource ? (
|
|
||||||
<LogsQB
|
|
||||||
source={DataSource.LOGS}
|
|
||||||
filterConfigs={listViewLogFilterConfigs}
|
|
||||||
panelType={panelType}
|
|
||||||
version={version}
|
|
||||||
isListViewPanel={isListViewPanel}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
{isTracesDataSource ? (
|
|
||||||
<TracesQB
|
|
||||||
source={DataSource.TRACES}
|
|
||||||
filterConfigs={listViewTracesFilterConfigs}
|
|
||||||
panelType={panelType}
|
|
||||||
version={version}
|
|
||||||
isListViewPanel={isListViewPanel}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
});
|
|
||||||
|
|
||||||
function QueryBuilderV2(props: QueryBuilderV2Props): JSX.Element {
|
useEffect(() => {
|
||||||
const { source, panelType, filterConfigs, isListViewPanel, version } = props;
|
if (currentDataSource !== initialDataSource || newPanelType !== panelType) {
|
||||||
|
if (newPanelType === PANEL_TYPES.BAR) {
|
||||||
|
handleSetConfig(PANEL_TYPES.BAR, DataSource.METRICS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handleSetConfig(newPanelType, currentDataSource);
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
handleSetConfig,
|
||||||
|
panelType,
|
||||||
|
initialDataSource,
|
||||||
|
currentDataSource,
|
||||||
|
newPanelType,
|
||||||
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<QueryBuilderV2Provider>
|
<QueryBuilderV2Provider>
|
||||||
<QueryBuilderV2Main
|
<div className="query-builder-v2">
|
||||||
source={source}
|
<div className="qb-content-container">
|
||||||
panelType={panelType}
|
{currentQuery.builder.queryData.map((query, index) => (
|
||||||
filterConfigs={filterConfigs}
|
<QueryV2
|
||||||
isListViewPanel={isListViewPanel}
|
key={query.queryName}
|
||||||
version={version}
|
index={index}
|
||||||
/>
|
query={query}
|
||||||
|
filterConfigs={filterConfigs}
|
||||||
|
queryComponents={queryComponents}
|
||||||
|
version={version}
|
||||||
|
isAvailableToDisable={false}
|
||||||
|
showSpanScopeSelector
|
||||||
|
queryVariant={config?.queryVariant || 'dropdown'}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{currentQuery.builder.queryFormulas.length > 0 && (
|
||||||
|
<div className="qb-formulas-container">
|
||||||
|
{currentQuery.builder.queryFormulas.map((formula, index) => {
|
||||||
|
const query =
|
||||||
|
currentQuery.builder.queryData[index] ||
|
||||||
|
currentQuery.builder.queryData[0];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={formula.queryName} className="qb-formula">
|
||||||
|
<Formula
|
||||||
|
filterConfigs={filterConfigs}
|
||||||
|
query={query}
|
||||||
|
formula={formula}
|
||||||
|
index={index}
|
||||||
|
isAdditionalFilterEnable={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<QueryFooter
|
||||||
|
addNewBuilderQuery={addNewBuilderQuery}
|
||||||
|
addNewFormula={addNewFormula}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="query-names-section">
|
||||||
|
{currentQuery.builder.queryData.map((query) => (
|
||||||
|
<div key={query.queryName} className="query-name">
|
||||||
|
{query.queryName}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{currentQuery.builder.queryFormulas.map((formula) => (
|
||||||
|
<div key={formula.queryName} className="formula-name">
|
||||||
|
{formula.queryName}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</QueryBuilderV2Provider>
|
</QueryBuilderV2Provider>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
export default QueryBuilderV2;
|
|
||||||
|
|||||||
@ -17,16 +17,20 @@ import QuerySearch from './QuerySearch/QuerySearch';
|
|||||||
|
|
||||||
export const QueryV2 = memo(function QueryV2({
|
export const QueryV2 = memo(function QueryV2({
|
||||||
index,
|
index,
|
||||||
|
queryVariant,
|
||||||
query,
|
query,
|
||||||
filterConfigs,
|
filterConfigs,
|
||||||
|
queryComponents,
|
||||||
isListViewPanel = false,
|
isListViewPanel = false,
|
||||||
version,
|
version,
|
||||||
showSpanScopeSelector = false,
|
showSpanScopeSelector = false,
|
||||||
source,
|
}: QueryProps): JSX.Element {
|
||||||
}: QueryProps & { source: DataSource }): JSX.Element {
|
|
||||||
const { cloneQuery } = useQueryBuilder();
|
const { cloneQuery } = useQueryBuilder();
|
||||||
|
|
||||||
const showFunctions = query?.functions?.length > 0;
|
const showFunctions = query?.functions?.length > 0;
|
||||||
|
const { dataSource } = query;
|
||||||
|
|
||||||
|
console.log('queryComponents', queryComponents);
|
||||||
|
|
||||||
const [isCollapsed, setIsCollapsed] = useState(false);
|
const [isCollapsed, setIsCollapsed] = useState(false);
|
||||||
|
|
||||||
@ -34,6 +38,7 @@ export const QueryV2 = memo(function QueryV2({
|
|||||||
handleChangeQueryData,
|
handleChangeQueryData,
|
||||||
handleDeleteQuery,
|
handleDeleteQuery,
|
||||||
handleQueryFunctionsUpdates,
|
handleQueryFunctionsUpdates,
|
||||||
|
handleChangeDataSource,
|
||||||
} = useQueryOperations({
|
} = useQueryOperations({
|
||||||
index,
|
index,
|
||||||
query,
|
query,
|
||||||
@ -61,7 +66,7 @@ export const QueryV2 = memo(function QueryV2({
|
|||||||
<div className="query-actions-container">
|
<div className="query-actions-container">
|
||||||
<div className="query-actions-left-container">
|
<div className="query-actions-left-container">
|
||||||
<QBEntityOptions
|
<QBEntityOptions
|
||||||
isMetricsDataSource={source === DataSource.METRICS}
|
isMetricsDataSource={dataSource === DataSource.METRICS}
|
||||||
showFunctions={
|
showFunctions={
|
||||||
(version && version === ENTITY_VERSION_V4) ||
|
(version && version === ENTITY_VERSION_V4) ||
|
||||||
query.dataSource === DataSource.LOGS ||
|
query.dataSource === DataSource.LOGS ||
|
||||||
@ -81,6 +86,8 @@ export const QueryV2 = memo(function QueryV2({
|
|||||||
showCloneOption={false}
|
showCloneOption={false}
|
||||||
isListViewPanel={isListViewPanel}
|
isListViewPanel={isListViewPanel}
|
||||||
index={index}
|
index={index}
|
||||||
|
queryVariant={queryVariant}
|
||||||
|
onChangeDataSource={handleChangeDataSource}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -111,7 +118,7 @@ export const QueryV2 = memo(function QueryV2({
|
|||||||
|
|
||||||
<div className="qb-elements-container">
|
<div className="qb-elements-container">
|
||||||
<div className="qb-search-container">
|
<div className="qb-search-container">
|
||||||
{source === DataSource.METRICS && (
|
{dataSource === DataSource.METRICS && (
|
||||||
<div className="metrics-select-container">
|
<div className="metrics-select-container">
|
||||||
<MetricsSelect query={query} index={0} version="v4" />
|
<MetricsSelect query={query} index={0} version="v4" />
|
||||||
</div>
|
</div>
|
||||||
@ -129,9 +136,9 @@ export const QueryV2 = memo(function QueryV2({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<QueryAggregation source={source} />
|
<QueryAggregation source={dataSource} />
|
||||||
|
|
||||||
{source === DataSource.METRICS && (
|
{dataSource === DataSource.METRICS && (
|
||||||
<MetricsAggregateSection query={query} index={0} version="v4" />
|
<MetricsAggregateSection query={query} index={0} version="v4" />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
.traces-qb {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
@ -1,88 +0,0 @@
|
|||||||
import './TracesQB.styles.scss';
|
|
||||||
|
|
||||||
import { ENTITY_VERSION_V4 } from 'constants/app';
|
|
||||||
import { Formula } from 'container/QueryBuilder/components/Formula';
|
|
||||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
|
||||||
import { useQueryOperations } from 'hooks/queryBuilder/useQueryBuilderOperations';
|
|
||||||
import { DataSource } from 'types/common/queryBuilder';
|
|
||||||
|
|
||||||
import { QueryBuilderV2Props } from '../QueryBuilderV2';
|
|
||||||
import QueryFooter from '../QueryV2/QueryFooter/QueryFooter';
|
|
||||||
import { QueryV2 } from '../QueryV2/QueryV2';
|
|
||||||
|
|
||||||
function TracesQB({ filterConfigs }: QueryBuilderV2Props): JSX.Element {
|
|
||||||
const version = ENTITY_VERSION_V4;
|
|
||||||
|
|
||||||
const { currentQuery, addNewFormula, addNewBuilderQuery } = useQueryBuilder();
|
|
||||||
|
|
||||||
const { isMetricsDataSource } = useQueryOperations({
|
|
||||||
index: 0,
|
|
||||||
query: currentQuery.builder.queryData[0],
|
|
||||||
filterConfigs,
|
|
||||||
isListViewPanel: false,
|
|
||||||
entityVersion: version,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="traces-qb">
|
|
||||||
<div className="qb-content-container">
|
|
||||||
{currentQuery.builder.queryData.map((query, index) => (
|
|
||||||
<QueryV2
|
|
||||||
key={query.queryName}
|
|
||||||
index={index}
|
|
||||||
query={query}
|
|
||||||
filterConfigs={filterConfigs}
|
|
||||||
version={version}
|
|
||||||
isAvailableToDisable={false}
|
|
||||||
queryVariant="static"
|
|
||||||
source={DataSource.TRACES}
|
|
||||||
showSpanScopeSelector
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{currentQuery.builder.queryFormulas.length > 0 && (
|
|
||||||
<div className="qb-formulas-container">
|
|
||||||
{currentQuery.builder.queryFormulas.map((formula, index) => {
|
|
||||||
const query =
|
|
||||||
currentQuery.builder.queryData[index] ||
|
|
||||||
currentQuery.builder.queryData[0];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div key={formula.queryName} className="qb-formula">
|
|
||||||
<Formula
|
|
||||||
filterConfigs={filterConfigs}
|
|
||||||
query={query}
|
|
||||||
formula={formula}
|
|
||||||
index={index}
|
|
||||||
isAdditionalFilterEnable={isMetricsDataSource}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<QueryFooter
|
|
||||||
addNewBuilderQuery={addNewBuilderQuery}
|
|
||||||
addNewFormula={addNewFormula}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="query-names-section">
|
|
||||||
{currentQuery.builder.queryData.map((query) => (
|
|
||||||
<div key={query.queryName} className="query-name">
|
|
||||||
{query.queryName}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{currentQuery.builder.queryFormulas.map((formula) => (
|
|
||||||
<div key={formula.queryName} className="formula-name">
|
|
||||||
{formula.queryName}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default TracesQB;
|
|
||||||
@ -1,13 +1,12 @@
|
|||||||
import './LogsExplorerQuerySection.styles.scss';
|
import './LogsExplorerQuerySection.styles.scss';
|
||||||
|
|
||||||
import QueryBuilderV2 from 'components/QueryBuilderV2/QueryBuilderV2';
|
import { QueryBuilderV2 } from 'components/QueryBuilderV2/QueryBuilderV2';
|
||||||
import {
|
import {
|
||||||
initialQueriesMap,
|
initialQueriesMap,
|
||||||
OPERATORS,
|
OPERATORS,
|
||||||
PANEL_TYPES,
|
PANEL_TYPES,
|
||||||
} from 'constants/queryBuilder';
|
} from 'constants/queryBuilder';
|
||||||
import ExplorerOrderBy from 'container/ExplorerOrderBy';
|
import ExplorerOrderBy from 'container/ExplorerOrderBy';
|
||||||
import { QueryBuilder } from 'container/QueryBuilder';
|
|
||||||
import { OrderByFilterProps } from 'container/QueryBuilder/filters/OrderByFilter/OrderByFilter.interfaces';
|
import { OrderByFilterProps } from 'container/QueryBuilder/filters/OrderByFilter/OrderByFilter.interfaces';
|
||||||
import QueryBuilderSearchV2 from 'container/QueryBuilder/filters/QueryBuilderSearchV2/QueryBuilderSearchV2';
|
import QueryBuilderSearchV2 from 'container/QueryBuilder/filters/QueryBuilderSearchV2/QueryBuilderSearchV2';
|
||||||
import { QueryBuilderProps } from 'container/QueryBuilder/QueryBuilder.interfaces';
|
import { QueryBuilderProps } from 'container/QueryBuilder/QueryBuilder.interfaces';
|
||||||
@ -16,8 +15,8 @@ import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
|||||||
import { useQueryOperations } from 'hooks/queryBuilder/useQueryBuilderOperations';
|
import { useQueryOperations } from 'hooks/queryBuilder/useQueryBuilderOperations';
|
||||||
import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
|
import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
|
||||||
import {
|
import {
|
||||||
|
ExplorerViews,
|
||||||
prepareQueryWithDefaultTimestamp,
|
prepareQueryWithDefaultTimestamp,
|
||||||
SELECTED_VIEWS,
|
|
||||||
} from 'pages/LogsExplorer/utils';
|
} from 'pages/LogsExplorer/utils';
|
||||||
import { memo, useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
@ -26,7 +25,7 @@ import { DataSource } from 'types/common/queryBuilder';
|
|||||||
function LogExplorerQuerySection({
|
function LogExplorerQuerySection({
|
||||||
selectedView,
|
selectedView,
|
||||||
}: {
|
}: {
|
||||||
selectedView: SELECTED_VIEWS;
|
selectedView: ExplorerViews;
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
const { currentQuery, updateAllQueriesOperators } = useQueryBuilder();
|
const { currentQuery, updateAllQueriesOperators } = useQueryBuilder();
|
||||||
|
|
||||||
@ -89,7 +88,7 @@ function LogExplorerQuerySection({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{selectedView === SELECTED_VIEWS.SEARCH && (
|
{selectedView === ExplorerViews.LIST && (
|
||||||
<div className="qb-search-view-container">
|
<div className="qb-search-view-container">
|
||||||
<QueryBuilderSearchV2
|
<QueryBuilderSearchV2
|
||||||
query={query}
|
query={query}
|
||||||
@ -99,25 +98,18 @@ function LogExplorerQuerySection({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{selectedView === SELECTED_VIEWS.QUERY_BUILDER && (
|
{(selectedView === ExplorerViews.TABLE ||
|
||||||
<QueryBuilder
|
selectedView === ExplorerViews.TIMESERIES ||
|
||||||
panelType={panelTypes}
|
selectedView === ExplorerViews.CLICKHOUSE) && (
|
||||||
|
<QueryBuilderV2
|
||||||
|
isListViewPanel={panelTypes === PANEL_TYPES.LIST}
|
||||||
config={{ initialDataSource: DataSource.LOGS, queryVariant: 'static' }}
|
config={{ initialDataSource: DataSource.LOGS, queryVariant: 'static' }}
|
||||||
|
panelType={panelTypes}
|
||||||
filterConfigs={filterConfigs}
|
filterConfigs={filterConfigs}
|
||||||
queryComponents={queryComponents}
|
queryComponents={queryComponents}
|
||||||
version="v3" // setting this to v3 as we this is rendered in logs explorer
|
version="v3" // setting this to v3 as we this is rendered in logs explorer
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{selectedView === SELECTED_VIEWS.QUERY_BUILDER_V2 && (
|
|
||||||
<QueryBuilderV2
|
|
||||||
source={DataSource.LOGS}
|
|
||||||
isListViewPanel={panelTypes === PANEL_TYPES.LIST}
|
|
||||||
panelType={panelTypes}
|
|
||||||
filterConfigs={filterConfigs}
|
|
||||||
version="v3" // setting this to v3 as we this is rendered in logs explorer
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -80,10 +80,54 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.logs-actions-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
height: 40px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
border-top: 1px solid var(--Slate-500, #161922);
|
||||||
|
border-bottom: 1px solid var(--Slate-500, #161922);
|
||||||
|
box-shadow: 0px 8px 6px 0px #0b0c0e;
|
||||||
|
|
||||||
|
.tab-options {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.tab-options-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-options-right {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.frequency-chart-view-controller {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.query-stats {
|
.query-stats {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
|
|
||||||
|
align-self: flex-end;
|
||||||
|
|
||||||
.rows {
|
.rows {
|
||||||
color: var(--bg-vanilla-400);
|
color: var(--bg-vanilla-400);
|
||||||
font-family: 'Geist Mono';
|
font-family: 'Geist Mono';
|
||||||
@ -110,13 +154,6 @@
|
|||||||
letter-spacing: 0.36px;
|
letter-spacing: 0.36px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.logs-actions-container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
|
|
||||||
.ant-btn {
|
.ant-btn {
|
||||||
border: none;
|
border: none;
|
||||||
@ -186,6 +223,14 @@
|
|||||||
background: var(--bg-robin-400);
|
background: var(--bg-robin-400);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.logs-actions-container {
|
||||||
|
.tab-options {
|
||||||
|
border-top: 1px solid var(--text-vanilla-300);
|
||||||
|
border-bottom: 1px solid var(--text-vanilla-300);
|
||||||
|
}
|
||||||
|
|
||||||
.query-stats {
|
.query-stats {
|
||||||
.rows {
|
.rows {
|
||||||
color: var(--bg-ink-400);
|
color: var(--bg-ink-400);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/* eslint-disable sonarjs/cognitive-complexity */
|
/* eslint-disable sonarjs/cognitive-complexity */
|
||||||
import './LogsExplorerViews.styles.scss';
|
import './LogsExplorerViews.styles.scss';
|
||||||
|
|
||||||
import { Button, Typography } from 'antd';
|
import { Button, Switch, Typography } from 'antd';
|
||||||
import { getQueryStats, WsDataEvent } from 'api/common/getQueryStats';
|
import { getQueryStats, WsDataEvent } from 'api/common/getQueryStats';
|
||||||
import logEvent from 'api/common/logEvent';
|
import logEvent from 'api/common/logEvent';
|
||||||
import { getYAxisFormattedValue } from 'components/Graph/yAxisConfig';
|
import { getYAxisFormattedValue } from 'components/Graph/yAxisConfig';
|
||||||
@ -47,7 +47,7 @@ import {
|
|||||||
set,
|
set,
|
||||||
} from 'lodash-es';
|
} from 'lodash-es';
|
||||||
import { Sliders } from 'lucide-react';
|
import { Sliders } from 'lucide-react';
|
||||||
import { SELECTED_VIEWS } from 'pages/LogsExplorer/utils';
|
import { ExplorerViews } from 'pages/LogsExplorer/utils';
|
||||||
import { useTimezone } from 'providers/Timezone';
|
import { useTimezone } from 'providers/Timezone';
|
||||||
import {
|
import {
|
||||||
memo,
|
memo,
|
||||||
@ -80,15 +80,13 @@ import { v4 } from 'uuid';
|
|||||||
|
|
||||||
import QueryStatus from './QueryStatus';
|
import QueryStatus from './QueryStatus';
|
||||||
|
|
||||||
function LogsExplorerViews({
|
function LogsExplorerViewsContainer({
|
||||||
selectedView,
|
selectedView,
|
||||||
showFrequencyChart,
|
|
||||||
setIsLoadingQueries,
|
setIsLoadingQueries,
|
||||||
listQueryKeyRef,
|
listQueryKeyRef,
|
||||||
chartQueryKeyRef,
|
chartQueryKeyRef,
|
||||||
}: {
|
}: {
|
||||||
selectedView: SELECTED_VIEWS;
|
selectedView: ExplorerViews;
|
||||||
showFrequencyChart: boolean;
|
|
||||||
setIsLoadingQueries: React.Dispatch<React.SetStateAction<boolean>>;
|
setIsLoadingQueries: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
listQueryKeyRef: MutableRefObject<any>;
|
listQueryKeyRef: MutableRefObject<any>;
|
||||||
@ -97,6 +95,7 @@ function LogsExplorerViews({
|
|||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
const { safeNavigate } = useSafeNavigate();
|
const { safeNavigate } = useSafeNavigate();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
const [showFrequencyChart, setShowFrequencyChart] = useState(true);
|
||||||
|
|
||||||
// this is to respect the panel type present in the URL rather than defaulting it to list always.
|
// this is to respect the panel type present in the URL rather than defaulting it to list always.
|
||||||
const panelTypes = useGetPanelTypesQueryParam(PANEL_TYPES.LIST);
|
const panelTypes = useGetPanelTypesQueryParam(PANEL_TYPES.LIST);
|
||||||
@ -240,15 +239,6 @@ function LogsExplorerViews({
|
|||||||
[currentQuery, selectedPanelType, updateAllQueriesOperators],
|
[currentQuery, selectedPanelType, updateAllQueriesOperators],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleModeChange = (panelType: PANEL_TYPES): void => {
|
|
||||||
if (selectedView === SELECTED_VIEWS.SEARCH) {
|
|
||||||
handleSetConfig(panelType, DataSource.LOGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
setShowFormatMenuItems(false);
|
|
||||||
handleExplorerTabChange(panelType);
|
|
||||||
};
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: listChartData,
|
data: listChartData,
|
||||||
isFetching: isFetchingListChartData,
|
isFetching: isFetchingListChartData,
|
||||||
@ -460,8 +450,7 @@ function LogsExplorerViews({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const shouldChangeView =
|
const shouldChangeView =
|
||||||
(isMultipleQueries || isGroupByExist) &&
|
(isMultipleQueries || isGroupByExist) && selectedView !== ExplorerViews.LIST;
|
||||||
selectedView !== SELECTED_VIEWS.SEARCH;
|
|
||||||
|
|
||||||
if (selectedPanelType === PANEL_TYPES.LIST && shouldChangeView) {
|
if (selectedPanelType === PANEL_TYPES.LIST && shouldChangeView) {
|
||||||
handleExplorerTabChange(PANEL_TYPES.TIME_SERIES);
|
handleExplorerTabChange(PANEL_TYPES.TIME_SERIES);
|
||||||
@ -481,11 +470,7 @@ function LogsExplorerViews({
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (selectedView && selectedView === ExplorerViews.LIST && handleSetConfig) {
|
||||||
selectedView &&
|
|
||||||
selectedView === SELECTED_VIEWS.SEARCH &&
|
|
||||||
handleSetConfig
|
|
||||||
) {
|
|
||||||
handleSetConfig(defaultTo(panelTypes, PANEL_TYPES.LIST), DataSource.LOGS);
|
handleSetConfig(defaultTo(panelTypes, PANEL_TYPES.LIST), DataSource.LOGS);
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
@ -651,111 +636,90 @@ function LogsExplorerViews({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="logs-explorer-views-container">
|
<div className="logs-explorer-views-container">
|
||||||
{showFrequencyChart && (
|
|
||||||
<LogsExplorerChart
|
|
||||||
className="logs-histogram"
|
|
||||||
isLoading={isFetchingListChartData || isLoadingListChartData}
|
|
||||||
data={chartData}
|
|
||||||
isLogsExplorerViews={panelType === PANEL_TYPES.LIST}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="logs-explorer-views-types">
|
<div className="logs-explorer-views-types">
|
||||||
<div className="views-tabs-container">
|
<div className="logs-actions-container">
|
||||||
<Button.Group className="views-tabs">
|
<div className="tab-options">
|
||||||
<Button
|
<div className="tab-options-left">
|
||||||
value={PANEL_TYPES.LIST}
|
{selectedPanelType === PANEL_TYPES.LIST && (
|
||||||
className={
|
<div className="frequency-chart-view-controller">
|
||||||
// eslint-disable-next-line sonarjs/no-duplicate-string
|
<Typography>Frequency chart</Typography>
|
||||||
selectedPanelType === PANEL_TYPES.LIST ? 'selected_view tab' : 'tab'
|
<Switch
|
||||||
}
|
size="small"
|
||||||
disabled={
|
checked={showFrequencyChart}
|
||||||
(isMultipleQueries || isGroupByExist) && selectedView !== 'search'
|
defaultChecked
|
||||||
}
|
onChange={(): void => setShowFrequencyChart(!showFrequencyChart)}
|
||||||
onClick={(): void => handleModeChange(PANEL_TYPES.LIST)}
|
/>
|
||||||
data-testid="logs-list-view"
|
</div>
|
||||||
>
|
)}
|
||||||
List view
|
</div>
|
||||||
</Button>
|
|
||||||
<Button
|
<div className="tab-options-right">
|
||||||
value={PANEL_TYPES.TIME_SERIES}
|
{selectedPanelType === PANEL_TYPES.LIST && (
|
||||||
className={
|
<>
|
||||||
// eslint-disable-next-line sonarjs/no-duplicate-string
|
<Download
|
||||||
selectedPanelType === PANEL_TYPES.TIME_SERIES
|
data={flattenLogData}
|
||||||
? 'selected_view tab'
|
isLoading={isFetching}
|
||||||
: 'tab'
|
fileName="log_data"
|
||||||
}
|
/>
|
||||||
onClick={(): void => handleModeChange(PANEL_TYPES.TIME_SERIES)}
|
<div className="format-options-container" ref={menuRef}>
|
||||||
data-testid="time-series-view"
|
<Button
|
||||||
>
|
className="periscope-btn"
|
||||||
Time series
|
onClick={handleToggleShowFormatOptions}
|
||||||
</Button>
|
icon={<Sliders size={14} />}
|
||||||
<Button
|
data-testid="periscope-btn"
|
||||||
value={PANEL_TYPES.TABLE}
|
/>
|
||||||
className={
|
|
||||||
// eslint-disable-next-line sonarjs/no-duplicate-string
|
{showFormatMenuItems && (
|
||||||
selectedPanelType === PANEL_TYPES.TABLE ? 'selected_view tab' : 'tab'
|
<LogsFormatOptionsMenu
|
||||||
}
|
title="FORMAT"
|
||||||
onClick={(): void => handleModeChange(PANEL_TYPES.TABLE)}
|
items={formatItems}
|
||||||
data-testid="table-view"
|
selectedOptionFormat={options.format}
|
||||||
>
|
config={config}
|
||||||
Table
|
/>
|
||||||
</Button>
|
)}
|
||||||
</Button.Group>
|
</div>
|
||||||
<div className="logs-actions-container">
|
</>
|
||||||
{selectedPanelType === PANEL_TYPES.LIST && (
|
)}
|
||||||
<div className="tab-options">
|
|
||||||
<Download
|
{(selectedPanelType === PANEL_TYPES.TIME_SERIES ||
|
||||||
data={flattenLogData}
|
selectedPanelType === PANEL_TYPES.TABLE) && (
|
||||||
isLoading={isFetching}
|
<div className="query-stats">
|
||||||
fileName="log_data"
|
<QueryStatus
|
||||||
/>
|
loading={isLoading || isFetching}
|
||||||
<div className="format-options-container" ref={menuRef}>
|
error={isError}
|
||||||
<Button
|
success={isSuccess}
|
||||||
className="periscope-btn"
|
|
||||||
onClick={handleToggleShowFormatOptions}
|
|
||||||
icon={<Sliders size={14} />}
|
|
||||||
data-testid="periscope-btn"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{showFormatMenuItems && (
|
{queryStats?.read_rows && (
|
||||||
<LogsFormatOptionsMenu
|
<Typography.Text className="rows">
|
||||||
title="FORMAT"
|
{getYAxisFormattedValue(queryStats.read_rows?.toString(), 'short')}{' '}
|
||||||
items={formatItems}
|
rows
|
||||||
selectedOptionFormat={options.format}
|
</Typography.Text>
|
||||||
config={config}
|
)}
|
||||||
/>
|
|
||||||
|
{queryStats?.elapsed_ms && (
|
||||||
|
<>
|
||||||
|
<div className="divider" />
|
||||||
|
<Typography.Text className="time">
|
||||||
|
{getYAxisFormattedValue(queryStats?.elapsed_ms?.toString(), 'ms')}
|
||||||
|
</Typography.Text>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
</div>
|
||||||
{(selectedPanelType === PANEL_TYPES.TIME_SERIES ||
|
|
||||||
selectedPanelType === PANEL_TYPES.TABLE) && (
|
|
||||||
<div className="query-stats">
|
|
||||||
<QueryStatus
|
|
||||||
loading={isLoading || isFetching}
|
|
||||||
error={isError}
|
|
||||||
success={isSuccess}
|
|
||||||
/>
|
|
||||||
{queryStats?.read_rows && (
|
|
||||||
<Typography.Text className="rows">
|
|
||||||
{getYAxisFormattedValue(queryStats.read_rows?.toString(), 'short')}{' '}
|
|
||||||
rows
|
|
||||||
</Typography.Text>
|
|
||||||
)}
|
|
||||||
{queryStats?.elapsed_ms && (
|
|
||||||
<>
|
|
||||||
<div className="divider" />
|
|
||||||
<Typography.Text className="time">
|
|
||||||
{getYAxisFormattedValue(queryStats?.elapsed_ms?.toString(), 'ms')}
|
|
||||||
</Typography.Text>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{selectedPanelType === PANEL_TYPES.LIST && showFrequencyChart && (
|
||||||
|
<LogsExplorerChart
|
||||||
|
className="logs-histogram"
|
||||||
|
isLoading={isFetchingListChartData || isLoadingListChartData}
|
||||||
|
data={chartData}
|
||||||
|
isLogsExplorerViews={panelType === PANEL_TYPES.LIST}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="logs-explorer-views-type-content">
|
<div className="logs-explorer-views-type-content">
|
||||||
{selectedPanelType === PANEL_TYPES.LIST && (
|
{selectedPanelType === PANEL_TYPES.LIST && (
|
||||||
<LogsExplorerList
|
<LogsExplorerList
|
||||||
@ -801,4 +765,4 @@ function LogsExplorerViews({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default memo(LogsExplorerViews);
|
export default memo(LogsExplorerViewsContainer);
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { useGetExplorerQueryRange } from 'hooks/queryBuilder/useGetExplorerQuery
|
|||||||
import { logsQueryRangeSuccessResponse } from 'mocks-server/__mockdata__/logs_query_range';
|
import { logsQueryRangeSuccessResponse } from 'mocks-server/__mockdata__/logs_query_range';
|
||||||
import { server } from 'mocks-server/server';
|
import { server } from 'mocks-server/server';
|
||||||
import { rest } from 'msw';
|
import { rest } from 'msw';
|
||||||
import { SELECTED_VIEWS } from 'pages/LogsExplorer/utils';
|
import { ExplorerViews } from 'pages/LogsExplorer/utils';
|
||||||
import { PreferenceContextProvider } from 'providers/preferences/context/PreferenceContextProvider';
|
import { PreferenceContextProvider } from 'providers/preferences/context/PreferenceContextProvider';
|
||||||
import { QueryBuilderContext } from 'providers/QueryBuilder';
|
import { QueryBuilderContext } from 'providers/QueryBuilder';
|
||||||
import { VirtuosoMockContext } from 'react-virtuoso';
|
import { VirtuosoMockContext } from 'react-virtuoso';
|
||||||
@ -127,8 +127,7 @@ const renderer = (): RenderResult =>
|
|||||||
>
|
>
|
||||||
<PreferenceContextProvider>
|
<PreferenceContextProvider>
|
||||||
<LogsExplorerViews
|
<LogsExplorerViews
|
||||||
selectedView={SELECTED_VIEWS.SEARCH}
|
selectedView={ExplorerViews.LIST}
|
||||||
showFrequencyChart
|
|
||||||
setIsLoadingQueries={(): void => {}}
|
setIsLoadingQueries={(): void => {}}
|
||||||
listQueryKeyRef={{ current: {} }}
|
listQueryKeyRef={{ current: {} }}
|
||||||
chartQueryKeyRef={{ current: {} }}
|
chartQueryKeyRef={{ current: {} }}
|
||||||
@ -212,8 +211,7 @@ describe('LogsExplorerViews -', () => {
|
|||||||
<QueryBuilderContext.Provider value={mockQueryBuilderContextValue}>
|
<QueryBuilderContext.Provider value={mockQueryBuilderContextValue}>
|
||||||
<PreferenceContextProvider>
|
<PreferenceContextProvider>
|
||||||
<LogsExplorerViews
|
<LogsExplorerViews
|
||||||
selectedView={SELECTED_VIEWS.SEARCH}
|
selectedView={ExplorerViews.LIST}
|
||||||
showFrequencyChart
|
|
||||||
setIsLoadingQueries={(): void => {}}
|
setIsLoadingQueries={(): void => {}}
|
||||||
listQueryKeyRef={{ current: {} }}
|
listQueryKeyRef={{ current: {} }}
|
||||||
chartQueryKeyRef={{ current: {} }}
|
chartQueryKeyRef={{ current: {} }}
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin: 10px 0;
|
margin: 4px 0;
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
|
||||||
.explore-header-left-actions {
|
.explore-header-left-actions {
|
||||||
@ -56,7 +56,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.explore-content {
|
.explore-content {
|
||||||
margin-top: 10px;
|
padding: 0 8px;
|
||||||
|
|
||||||
.ant-space {
|
.ant-space {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
|
|||||||
@ -3,10 +3,11 @@ import './Explorer.styles.scss';
|
|||||||
import * as Sentry from '@sentry/react';
|
import * as Sentry from '@sentry/react';
|
||||||
import { Switch } from 'antd';
|
import { Switch } from 'antd';
|
||||||
import logEvent from 'api/common/logEvent';
|
import logEvent from 'api/common/logEvent';
|
||||||
import QueryBuilderV2 from 'components/QueryBuilderV2/QueryBuilderV2';
|
import { QueryBuilderV2 } from 'components/QueryBuilderV2/QueryBuilderV2';
|
||||||
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
|
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import ExplorerOptionWrapper from 'container/ExplorerOptions/ExplorerOptionWrapper';
|
import ExplorerOptionWrapper from 'container/ExplorerOptions/ExplorerOptionWrapper';
|
||||||
import RightToolbarActions from 'container/QueryBuilder/components/ToolbarActions/RightToolbarActions';
|
import RightToolbarActions from 'container/QueryBuilder/components/ToolbarActions/RightToolbarActions';
|
||||||
|
import { QueryBuilderProps } from 'container/QueryBuilder/QueryBuilder.interfaces';
|
||||||
import DateTimeSelector from 'container/TopNav/DateTimeSelectionV2';
|
import DateTimeSelector from 'container/TopNav/DateTimeSelectionV2';
|
||||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||||
import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
|
import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
|
||||||
@ -102,6 +103,11 @@ function Explorer(): JSX.Element {
|
|||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const queryComponents = useMemo(
|
||||||
|
(): QueryBuilderProps['queryComponents'] => ({}),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sentry.ErrorBoundary fallback={<ErrorBoundaryFallback />}>
|
<Sentry.ErrorBoundary fallback={<ErrorBoundaryFallback />}>
|
||||||
<div className="metrics-explorer-explore-container">
|
<div className="metrics-explorer-explore-container">
|
||||||
@ -121,8 +127,12 @@ function Explorer(): JSX.Element {
|
|||||||
</div>
|
</div>
|
||||||
{/* <QuerySection /> */}
|
{/* <QuerySection /> */}
|
||||||
<QueryBuilderV2
|
<QueryBuilderV2
|
||||||
source={DataSource.METRICS}
|
config={{ initialDataSource: DataSource.METRICS, queryVariant: 'static' }}
|
||||||
query={currentQuery.builder.queryData[0]}
|
panelType={PANEL_TYPES.TIME_SERIES}
|
||||||
|
queryComponents={queryComponents}
|
||||||
|
showFunctions={false}
|
||||||
|
version="v3"
|
||||||
|
isListViewPanel
|
||||||
/>
|
/>
|
||||||
{/* TODO: Enable once we have resolved all related metrics issues */}
|
{/* TODO: Enable once we have resolved all related metrics issues */}
|
||||||
{/* <Button.Group className="explore-tabs">
|
{/* <Button.Group className="explore-tabs">
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import './QuerySection.styles.scss';
|
import './QuerySection.styles.scss';
|
||||||
|
|
||||||
import { Color } from '@signozhq/design-tokens';
|
import { Color } from '@signozhq/design-tokens';
|
||||||
import { Button, Select, Tabs, Typography } from 'antd';
|
import { Button, Tabs, Typography } from 'antd';
|
||||||
import logEvent from 'api/common/logEvent';
|
import logEvent from 'api/common/logEvent';
|
||||||
import PromQLIcon from 'assets/Dashboard/PromQl';
|
import PromQLIcon from 'assets/Dashboard/PromQl';
|
||||||
import QueryBuilderV2 from 'components/QueryBuilderV2/QueryBuilderV2';
|
import { QueryBuilderV2 } from 'components/QueryBuilderV2/QueryBuilderV2';
|
||||||
import TextToolTip from 'components/TextToolTip';
|
import TextToolTip from 'components/TextToolTip';
|
||||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import { QBShortcuts } from 'constants/shortcuts/QBShortcuts';
|
import { QBShortcuts } from 'constants/shortcuts/QBShortcuts';
|
||||||
@ -27,14 +27,13 @@ import {
|
|||||||
getPreviousWidgets,
|
getPreviousWidgets,
|
||||||
getSelectedWidgetIndex,
|
getSelectedWidgetIndex,
|
||||||
} from 'providers/Dashboard/util';
|
} from 'providers/Dashboard/util';
|
||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useMemo } from 'react';
|
||||||
import { UseQueryResult } from 'react-query';
|
import { UseQueryResult } from 'react-query';
|
||||||
import { SuccessResponse } from 'types/api';
|
import { SuccessResponse } from 'types/api';
|
||||||
import { Widgets } from 'types/api/dashboard/getAll';
|
import { Widgets } from 'types/api/dashboard/getAll';
|
||||||
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
||||||
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
import { EQueryType } from 'types/common/dashboard';
|
import { EQueryType } from 'types/common/dashboard';
|
||||||
import { DataSource } from 'types/common/queryBuilder';
|
|
||||||
|
|
||||||
import ClickHouseQueryContainer from './QueryBuilder/clickHouse';
|
import ClickHouseQueryContainer from './QueryBuilder/clickHouse';
|
||||||
import PromQLQueryContainer from './QueryBuilder/promQL';
|
import PromQLQueryContainer from './QueryBuilder/promQL';
|
||||||
@ -49,10 +48,6 @@ function QuerySection({
|
|||||||
|
|
||||||
const { selectedDashboard, setSelectedDashboard } = useDashboard();
|
const { selectedDashboard, setSelectedDashboard } = useDashboard();
|
||||||
|
|
||||||
const [selectedDataSource, setSelectedDataSource] = useState<DataSource>(
|
|
||||||
DataSource.METRICS,
|
|
||||||
);
|
|
||||||
|
|
||||||
const isDarkMode = useIsDarkMode();
|
const isDarkMode = useIsDarkMode();
|
||||||
|
|
||||||
const { widgets } = selectedDashboard?.data || {};
|
const { widgets } = selectedDashboard?.data || {};
|
||||||
@ -148,6 +143,11 @@ function QuerySection({
|
|||||||
return config;
|
return config;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const queryComponents = useMemo(
|
||||||
|
(): QueryBuilderProps['queryComponents'] => ({}),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
const items = useMemo(() => {
|
const items = useMemo(() => {
|
||||||
const supportedQueryTypes = PANEL_TYPE_TO_QUERY_TYPES[selectedGraph] || [];
|
const supportedQueryTypes = PANEL_TYPE_TO_QUERY_TYPES[selectedGraph] || [];
|
||||||
|
|
||||||
@ -157,20 +157,12 @@ function QuerySection({
|
|||||||
label: 'Query Builder',
|
label: 'Query Builder',
|
||||||
component: (
|
component: (
|
||||||
<div className="query-builder-v2-container">
|
<div className="query-builder-v2-container">
|
||||||
<Select
|
|
||||||
onChange={setSelectedDataSource}
|
|
||||||
value={selectedDataSource}
|
|
||||||
options={Object.values(DataSource).map((dataSource) => ({
|
|
||||||
label: dataSource,
|
|
||||||
value: dataSource,
|
|
||||||
}))}
|
|
||||||
/>
|
|
||||||
<QueryBuilderV2
|
<QueryBuilderV2
|
||||||
panelType={selectedGraph}
|
panelType={selectedGraph}
|
||||||
filterConfigs={filterConfigs}
|
filterConfigs={filterConfigs}
|
||||||
version={selectedDashboard?.data?.version || 'v3'}
|
version={selectedDashboard?.data?.version || 'v3'}
|
||||||
isListViewPanel={selectedGraph === PANEL_TYPES.LIST}
|
isListViewPanel={selectedGraph === PANEL_TYPES.LIST}
|
||||||
source={selectedDataSource}
|
queryComponents={queryComponents}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
@ -203,11 +195,11 @@ function QuerySection({
|
|||||||
children: queryTypeComponents[queryType].component,
|
children: queryTypeComponents[queryType].component,
|
||||||
}));
|
}));
|
||||||
}, [
|
}, [
|
||||||
|
queryComponents,
|
||||||
selectedGraph,
|
selectedGraph,
|
||||||
filterConfigs,
|
filterConfigs,
|
||||||
selectedDashboard?.data?.version,
|
selectedDashboard?.data?.version,
|
||||||
isDarkMode,
|
isDarkMode,
|
||||||
selectedDataSource,
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import {
|
|||||||
} from 'types/api/queryBuilder/queryBuilderData';
|
} from 'types/api/queryBuilder/queryBuilderData';
|
||||||
import { DataSource } from 'types/common/queryBuilder';
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
|
|
||||||
|
import { DataSourceDropdown } from '..';
|
||||||
import QueryFunctions from '../QueryFunctions/QueryFunctions';
|
import QueryFunctions from '../QueryFunctions/QueryFunctions';
|
||||||
|
|
||||||
interface QBEntityOptionsProps {
|
interface QBEntityOptionsProps {
|
||||||
@ -40,8 +41,11 @@ interface QBEntityOptionsProps {
|
|||||||
showCloneOption?: boolean;
|
showCloneOption?: boolean;
|
||||||
isListViewPanel?: boolean;
|
isListViewPanel?: boolean;
|
||||||
index?: number;
|
index?: number;
|
||||||
|
queryVariant?: 'dropdown' | 'static';
|
||||||
|
onChangeDataSource?: (value: DataSource) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||||
export default function QBEntityOptions({
|
export default function QBEntityOptions({
|
||||||
query,
|
query,
|
||||||
isMetricsDataSource,
|
isMetricsDataSource,
|
||||||
@ -58,6 +62,8 @@ export default function QBEntityOptions({
|
|||||||
showCloneOption,
|
showCloneOption,
|
||||||
onCloneQuery,
|
onCloneQuery,
|
||||||
index,
|
index,
|
||||||
|
queryVariant,
|
||||||
|
onChangeDataSource,
|
||||||
}: QBEntityOptionsProps): JSX.Element {
|
}: QBEntityOptionsProps): JSX.Element {
|
||||||
const handleCloneEntity = (): void => {
|
const handleCloneEntity = (): void => {
|
||||||
if (isFunction(onCloneQuery)) {
|
if (isFunction(onCloneQuery)) {
|
||||||
@ -117,6 +123,21 @@ export default function QBEntityOptions({
|
|||||||
{entityData.queryName}
|
{entityData.queryName}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
{queryVariant === 'dropdown' && (
|
||||||
|
<div className="query-data-source">
|
||||||
|
<DataSourceDropdown
|
||||||
|
onChange={(value): void => {
|
||||||
|
if (onChangeDataSource) {
|
||||||
|
onChangeDataSource(value);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
value={query?.dataSource || DataSource.METRICS}
|
||||||
|
isListViewPanel={isListViewPanel}
|
||||||
|
className="query-data-source-dropdown"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{showFunctions &&
|
{showFunctions &&
|
||||||
(isMetricsDataSource || isLogsDataSource) &&
|
(isMetricsDataSource || isLogsDataSource) &&
|
||||||
query &&
|
query &&
|
||||||
@ -161,4 +182,6 @@ QBEntityOptions.defaultProps = {
|
|||||||
onDelete: noop,
|
onDelete: noop,
|
||||||
showDeleteButton: false,
|
showDeleteButton: false,
|
||||||
showCloneOption: true,
|
showCloneOption: true,
|
||||||
|
queryVariant: 'static',
|
||||||
|
onChangeDataSource: noop,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -350,6 +350,7 @@ export const Query = memo(function Query({
|
|||||||
showDeleteButton={currentQuery.builder.queryData.length > 1}
|
showDeleteButton={currentQuery.builder.queryData.length > 1}
|
||||||
isListViewPanel={isListViewPanel}
|
isListViewPanel={isListViewPanel}
|
||||||
index={index}
|
index={index}
|
||||||
|
queryVariant={queryVariant}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{!isCollapse && (
|
{!isCollapse && (
|
||||||
|
|||||||
@ -1,35 +1,31 @@
|
|||||||
|
/* eslint-disable sonarjs/no-duplicate-string */
|
||||||
import './ToolbarActions.styles.scss';
|
import './ToolbarActions.styles.scss';
|
||||||
|
|
||||||
import { FilterOutlined } from '@ant-design/icons';
|
import { FilterOutlined } from '@ant-design/icons';
|
||||||
import { Button, Switch, Tooltip, Typography } from 'antd';
|
import { Button, Tooltip } from 'antd';
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import { Atom, Binoculars, SquareMousePointer, Terminal } from 'lucide-react';
|
import { Atom, Binoculars, SquareMousePointer, Terminal } from 'lucide-react';
|
||||||
import { SELECTED_VIEWS } from 'pages/LogsExplorer/utils';
|
import { ExplorerViews } from 'pages/LogsExplorer/utils';
|
||||||
|
|
||||||
interface LeftToolbarActionsProps {
|
interface LeftToolbarActionsProps {
|
||||||
items: any;
|
items: any;
|
||||||
selectedView: string;
|
selectedView: string;
|
||||||
onToggleHistrogramVisibility: () => void;
|
onChangeSelectedView: (view: ExplorerViews) => void;
|
||||||
onChangeSelectedView: (view: SELECTED_VIEWS) => void;
|
|
||||||
showFrequencyChart: boolean;
|
|
||||||
showFilter: boolean;
|
showFilter: boolean;
|
||||||
handleFilterVisibilityChange: () => void;
|
handleFilterVisibilityChange: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const activeTab = 'active-tab';
|
const activeTab = 'active-tab';
|
||||||
const actionBtn = 'action-btn';
|
|
||||||
export const queryBuilder = 'query-builder';
|
|
||||||
export const queryBuilderV2 = 'query-builder-v2';
|
|
||||||
export default function LeftToolbarActions({
|
export default function LeftToolbarActions({
|
||||||
items,
|
items,
|
||||||
selectedView,
|
selectedView,
|
||||||
onToggleHistrogramVisibility,
|
|
||||||
onChangeSelectedView,
|
onChangeSelectedView,
|
||||||
showFrequencyChart,
|
|
||||||
showFilter,
|
showFilter,
|
||||||
handleFilterVisibilityChange,
|
handleFilterVisibilityChange,
|
||||||
}: LeftToolbarActionsProps): JSX.Element {
|
}: LeftToolbarActionsProps): JSX.Element {
|
||||||
const { clickhouse, search, queryBuilder: QB } = items;
|
const { clickhouse, list, timeseries, table, trace } = items;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="left-toolbar">
|
<div className="left-toolbar">
|
||||||
@ -41,72 +37,90 @@ export default function LeftToolbarActions({
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
<div className="left-toolbar-query-actions">
|
<div className="left-toolbar-query-actions">
|
||||||
<Tooltip title="Search">
|
{list?.show && (
|
||||||
<Button
|
<Tooltip title="List View">
|
||||||
disabled={search.disabled}
|
<Button
|
||||||
className={cx(
|
disabled={list.disabled}
|
||||||
'search',
|
className={cx(
|
||||||
actionBtn,
|
'list-view-tab',
|
||||||
selectedView === 'search' ? activeTab : '',
|
'explorer-view-option',
|
||||||
)}
|
selectedView === list.key ? activeTab : '',
|
||||||
onClick={(): void => onChangeSelectedView(SELECTED_VIEWS.SEARCH)}
|
)}
|
||||||
>
|
onClick={(): void => onChangeSelectedView(list.key)}
|
||||||
<SquareMousePointer size={14} data-testid="search-view" />
|
>
|
||||||
</Button>
|
<SquareMousePointer size={14} data-testid="search-view" />
|
||||||
</Tooltip>
|
List View
|
||||||
<Tooltip title="Query Builder">
|
</Button>
|
||||||
<Button
|
</Tooltip>
|
||||||
disabled={QB.disabled}
|
|
||||||
className={cx(
|
|
||||||
queryBuilder,
|
|
||||||
actionBtn,
|
|
||||||
selectedView === queryBuilder ? activeTab : '',
|
|
||||||
)}
|
|
||||||
onClick={(): void => onChangeSelectedView(SELECTED_VIEWS.QUERY_BUILDER)}
|
|
||||||
>
|
|
||||||
<Atom size={14} data-testid="query-builder-view" />
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
{clickhouse?.show && (
|
|
||||||
<Button
|
|
||||||
disabled={clickhouse.disabled}
|
|
||||||
className={cx(
|
|
||||||
SELECTED_VIEWS.CLICKHOUSE,
|
|
||||||
actionBtn,
|
|
||||||
selectedView === SELECTED_VIEWS.CLICKHOUSE ? activeTab : '',
|
|
||||||
)}
|
|
||||||
onClick={(): void => onChangeSelectedView(SELECTED_VIEWS.CLICKHOUSE)}
|
|
||||||
>
|
|
||||||
<Terminal size={14} data-testid="clickhouse-view" />
|
|
||||||
</Button>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Tooltip title="Query Builder V2">
|
{trace?.show && (
|
||||||
<Button
|
<Tooltip title="Trace View">
|
||||||
disabled={QB.disabled}
|
<Button
|
||||||
className={cx(
|
disabled={trace.disabled}
|
||||||
queryBuilderV2,
|
className={cx(
|
||||||
actionBtn,
|
'trace-view-tab',
|
||||||
selectedView === queryBuilderV2 ? activeTab : '',
|
'explorer-view-option',
|
||||||
)}
|
selectedView === trace.key ? activeTab : '',
|
||||||
onClick={(): void =>
|
)}
|
||||||
onChangeSelectedView(SELECTED_VIEWS.QUERY_BUILDER_V2)
|
onClick={(): void => onChangeSelectedView(trace.key)}
|
||||||
}
|
>
|
||||||
>
|
<SquareMousePointer size={14} data-testid="trace-view" />
|
||||||
<Binoculars size={14} data-testid="query-builder-view-v2" />
|
Trace View
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
)}
|
||||||
|
|
||||||
<div className="frequency-chart-view-controller">
|
{timeseries?.show && (
|
||||||
<Typography>Frequency chart</Typography>
|
<Tooltip title="Time Series">
|
||||||
<Switch
|
<Button
|
||||||
size="small"
|
disabled={timeseries.disabled}
|
||||||
checked={showFrequencyChart}
|
className={cx(
|
||||||
defaultChecked
|
'timeseries-view-tab',
|
||||||
onChange={onToggleHistrogramVisibility}
|
'explorer-view-option',
|
||||||
/>
|
selectedView === timeseries.key ? activeTab : '',
|
||||||
|
)}
|
||||||
|
onClick={(): void => onChangeSelectedView(timeseries.key)}
|
||||||
|
>
|
||||||
|
<Atom size={14} data-testid="query-builder-view" />
|
||||||
|
Time Series
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{clickhouse?.show && (
|
||||||
|
<Tooltip title="Clickhouse">
|
||||||
|
<Button
|
||||||
|
disabled={clickhouse.disabled}
|
||||||
|
className={cx(
|
||||||
|
'clickhouse-view-tab',
|
||||||
|
'explorer-view-option',
|
||||||
|
selectedView === clickhouse.key ? activeTab : '',
|
||||||
|
)}
|
||||||
|
onClick={(): void => onChangeSelectedView(clickhouse.key)}
|
||||||
|
>
|
||||||
|
<Terminal size={14} data-testid="clickhouse-view" />
|
||||||
|
Clickhouse
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{table?.show && (
|
||||||
|
<Tooltip title="Table">
|
||||||
|
<Button
|
||||||
|
disabled={table.disabled}
|
||||||
|
className={cx(
|
||||||
|
'table-view-tab',
|
||||||
|
'explorer-view-option',
|
||||||
|
selectedView === table.key ? activeTab : '',
|
||||||
|
)}
|
||||||
|
onClick={(): void => onChangeSelectedView(table.key)}
|
||||||
|
>
|
||||||
|
<Binoculars size={14} data-testid="query-builder-view-v2" />
|
||||||
|
Table
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -25,14 +25,16 @@
|
|||||||
width: 14px;
|
width: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-btn {
|
.explorer-view-option {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
flex-direction: row;
|
||||||
border: none;
|
border: none;
|
||||||
padding: 9px;
|
padding: 9px;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
&.active-tab {
|
&.active-tab {
|
||||||
background-color: var(--bg-slate-400);
|
background-color: var(--bg-slate-400);
|
||||||
@ -43,9 +45,6 @@
|
|||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.action-btn + .action-btn {
|
|
||||||
border-left: 1px solid var(--bg-slate-400);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.frequency-chart-view-controller {
|
.frequency-chart-view-controller {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import { SELECTED_VIEWS } from 'pages/LogsExplorer/utils';
|
import { ExplorerViews } from 'pages/LogsExplorer/utils';
|
||||||
import MockQueryClientProvider from 'providers/test/MockQueryClientProvider';
|
import MockQueryClientProvider from 'providers/test/MockQueryClientProvider';
|
||||||
|
|
||||||
import LeftToolbarActions from '../LeftToolbarActions';
|
import LeftToolbarActions from '../LeftToolbarActions';
|
||||||
@ -9,7 +9,6 @@ import RightToolbarActions from '../RightToolbarActions';
|
|||||||
describe('ToolbarActions', () => {
|
describe('ToolbarActions', () => {
|
||||||
it('LeftToolbarActions - renders correctly with default props', async () => {
|
it('LeftToolbarActions - renders correctly with default props', async () => {
|
||||||
const handleChangeSelectedView = jest.fn();
|
const handleChangeSelectedView = jest.fn();
|
||||||
const handleToggleShowFrequencyChart = jest.fn();
|
|
||||||
const { queryByTestId } = render(
|
const { queryByTestId } = render(
|
||||||
<LeftToolbarActions
|
<LeftToolbarActions
|
||||||
items={{
|
items={{
|
||||||
@ -31,10 +30,8 @@ describe('ToolbarActions', () => {
|
|||||||
disabled: false,
|
disabled: false,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
selectedView={SELECTED_VIEWS.SEARCH}
|
selectedView={ExplorerViews.LIST}
|
||||||
onChangeSelectedView={handleChangeSelectedView}
|
onChangeSelectedView={handleChangeSelectedView}
|
||||||
onToggleHistrogramVisibility={handleToggleShowFrequencyChart}
|
|
||||||
showFrequencyChart
|
|
||||||
showFilter
|
showFilter
|
||||||
handleFilterVisibilityChange={(): void => {}}
|
handleFilterVisibilityChange={(): void => {}}
|
||||||
/>,
|
/>,
|
||||||
@ -77,10 +74,8 @@ describe('ToolbarActions', () => {
|
|||||||
show: true,
|
show: true,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
selectedView={SELECTED_VIEWS.QUERY_BUILDER}
|
selectedView={ExplorerViews.TIMESERIES}
|
||||||
onChangeSelectedView={handleChangeSelectedView}
|
onChangeSelectedView={handleChangeSelectedView}
|
||||||
onToggleHistrogramVisibility={handleToggleShowFrequencyChart}
|
|
||||||
showFrequencyChart
|
|
||||||
showFilter
|
showFilter
|
||||||
handleFilterVisibilityChange={(): void => {}}
|
handleFilterVisibilityChange={(): void => {}}
|
||||||
/>,
|
/>,
|
||||||
|
|||||||
@ -0,0 +1,11 @@
|
|||||||
|
.time-series-view {
|
||||||
|
height: 50vh;
|
||||||
|
min-height: 350px;
|
||||||
|
padding: 0px 12px;
|
||||||
|
|
||||||
|
.ant-card-body {
|
||||||
|
height: 50vh;
|
||||||
|
min-height: 350px;
|
||||||
|
padding: 0px 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -33,8 +33,6 @@ import { GlobalReducer } from 'types/reducer/globalTime';
|
|||||||
import uPlot from 'uplot';
|
import uPlot from 'uplot';
|
||||||
import { getTimeRange } from 'utils/getTimeRange';
|
import { getTimeRange } from 'utils/getTimeRange';
|
||||||
|
|
||||||
import { Container } from './styles';
|
|
||||||
|
|
||||||
function TimeSeriesView({
|
function TimeSeriesView({
|
||||||
data,
|
data,
|
||||||
isLoading,
|
isLoading,
|
||||||
@ -162,7 +160,7 @@ function TimeSeriesView({
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<div className="time-series-view">
|
||||||
{isError && <LogsError />}
|
{isError && <LogsError />}
|
||||||
<div
|
<div
|
||||||
className="graph-container"
|
className="graph-container"
|
||||||
@ -204,7 +202,7 @@ function TimeSeriesView({
|
|||||||
!isEmpty(chartData?.[0]) &&
|
!isEmpty(chartData?.[0]) &&
|
||||||
chartOptions && <Uplot data={chartData} options={chartOptions} />}
|
chartOptions && <Uplot data={chartData} options={chartOptions} />}
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import './TimeSeriesView.styles.scss';
|
||||||
|
|
||||||
import { ENTITY_VERSION_V4 } from 'constants/app';
|
import { ENTITY_VERSION_V4 } from 'constants/app';
|
||||||
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
|
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
||||||
|
|||||||
@ -0,0 +1,4 @@
|
|||||||
|
.trace-explorer-controls {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
import './ListView.styles.scss';
|
||||||
|
|
||||||
import logEvent from 'api/common/logEvent';
|
import logEvent from 'api/common/logEvent';
|
||||||
import { ResizeTable } from 'components/ResizeTable';
|
import { ResizeTable } from 'components/ResizeTable';
|
||||||
import { ENTITY_VERSION_V4 } from 'constants/app';
|
import { ENTITY_VERSION_V4 } from 'constants/app';
|
||||||
@ -167,12 +169,14 @@ function ListView({ isFilterApplied }: ListViewProps): JSX.Element {
|
|||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
{transformedQueryTableData.length !== 0 && (
|
{transformedQueryTableData.length !== 0 && (
|
||||||
<TraceExplorerControls
|
<div className="trace-explorer-controls">
|
||||||
isLoading={isFetching}
|
<TraceExplorerControls
|
||||||
totalCount={totalCount}
|
isLoading={isFetching}
|
||||||
config={config}
|
totalCount={totalCount}
|
||||||
perPageOptions={PER_PAGE_OPTIONS}
|
config={config}
|
||||||
/>
|
perPageOptions={PER_PAGE_OPTIONS}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isError && <ErrorText>{data?.error || 'Something went wrong'}</ErrorText>}
|
{isError && <ErrorText>{data?.error || 'Something went wrong'}</ErrorText>}
|
||||||
|
|||||||
@ -1,18 +1,25 @@
|
|||||||
import { Button } from 'antd';
|
import { QueryBuilderV2 } from 'components/QueryBuilderV2/QueryBuilderV2';
|
||||||
|
// import QuerySearch from 'components/QueryBuilderV2/QueryV2/QuerySearch/QuerySearch';
|
||||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import ExplorerOrderBy from 'container/ExplorerOrderBy';
|
import ExplorerOrderBy from 'container/ExplorerOrderBy';
|
||||||
import { QueryBuilder } from 'container/QueryBuilder';
|
|
||||||
import { OrderByFilterProps } from 'container/QueryBuilder/filters/OrderByFilter/OrderByFilter.interfaces';
|
import { OrderByFilterProps } from 'container/QueryBuilder/filters/OrderByFilter/OrderByFilter.interfaces';
|
||||||
|
// import SpanScopeSelector from 'container/QueryBuilder/filters/QueryBuilderSearchV2/SpanScopeSelector';
|
||||||
import { QueryBuilderProps } from 'container/QueryBuilder/QueryBuilder.interfaces';
|
import { QueryBuilderProps } from 'container/QueryBuilder/QueryBuilder.interfaces';
|
||||||
import { useGetPanelTypesQueryParam } from 'hooks/queryBuilder/useGetPanelTypesQueryParam';
|
import { useGetPanelTypesQueryParam } from 'hooks/queryBuilder/useGetPanelTypesQueryParam';
|
||||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
// import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||||
import { memo, useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import { DataSource } from 'types/common/queryBuilder';
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
|
|
||||||
import { ButtonWrapper, Container } from './styles';
|
import { Container } from './styles';
|
||||||
|
|
||||||
function QuerySection(): JSX.Element {
|
function QuerySection({
|
||||||
const { handleRunQuery } = useQueryBuilder();
|
selectedView,
|
||||||
|
}: {
|
||||||
|
selectedView: PANEL_TYPES;
|
||||||
|
}): JSX.Element {
|
||||||
|
// const { currentQuery } = useQueryBuilder();
|
||||||
|
|
||||||
|
// const queryName = currentQuery?.builder?.queryData[0]?.queryName || '';
|
||||||
|
|
||||||
const panelTypes = useGetPanelTypesQueryParam(PANEL_TYPES.LIST);
|
const panelTypes = useGetPanelTypesQueryParam(PANEL_TYPES.LIST);
|
||||||
|
|
||||||
@ -43,25 +50,30 @@ function QuerySection(): JSX.Element {
|
|||||||
};
|
};
|
||||||
}, [panelTypes, renderOrderBy]);
|
}, [panelTypes, renderOrderBy]);
|
||||||
|
|
||||||
|
console.log('query - section - selectedView', selectedView);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<QueryBuilder
|
{/* {(selectedView === 'list' || selectedView === 'trace') && (
|
||||||
panelType={panelTypes}
|
<div className="qb-search-view-container">
|
||||||
config={{
|
<QuerySearch />
|
||||||
queryVariant: 'static',
|
|
||||||
initialDataSource: DataSource.TRACES,
|
<div className="traces-search-filter-in">in</div>
|
||||||
}}
|
|
||||||
filterConfigs={filterConfigs}
|
<SpanScopeSelector queryName={queryName} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{(selectedView === 'graph' || selectedView === 'table') && ( */}
|
||||||
|
<QueryBuilderV2
|
||||||
|
isListViewPanel={panelTypes === PANEL_TYPES.LIST}
|
||||||
|
config={{ initialDataSource: DataSource.TRACES, queryVariant: 'static' }}
|
||||||
queryComponents={queryComponents}
|
queryComponents={queryComponents}
|
||||||
|
panelType={panelTypes}
|
||||||
|
filterConfigs={filterConfigs}
|
||||||
version="v3" // setting this to v3 as we this is rendered in logs explorer
|
version="v3" // setting this to v3 as we this is rendered in logs explorer
|
||||||
actions={
|
|
||||||
<ButtonWrapper>
|
|
||||||
<Button onClick={(): void => handleRunQuery()} type="primary">
|
|
||||||
Run Query
|
|
||||||
</Button>
|
|
||||||
</ButtonWrapper>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
|
{/* )} */}
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,6 +58,8 @@ export const useHandleExplorerTabChange = (): {
|
|||||||
currentQueryData?: ICurrentQueryData,
|
currentQueryData?: ICurrentQueryData,
|
||||||
redirectToUrl?: typeof ROUTES[keyof typeof ROUTES],
|
redirectToUrl?: typeof ROUTES[keyof typeof ROUTES],
|
||||||
) => {
|
) => {
|
||||||
|
console.log('type', type);
|
||||||
|
|
||||||
const newPanelType = type as PANEL_TYPES;
|
const newPanelType = type as PANEL_TYPES;
|
||||||
|
|
||||||
if (newPanelType === panelType && !currentQueryData) return;
|
if (newPanelType === panelType && !currentQueryData) return;
|
||||||
|
|||||||
@ -8,8 +8,9 @@ import ExplorerCard from 'components/ExplorerCard/ExplorerCard';
|
|||||||
import QuickFilters from 'components/QuickFilters/QuickFilters';
|
import QuickFilters from 'components/QuickFilters/QuickFilters';
|
||||||
import { QuickFiltersSource, SignalType } from 'components/QuickFilters/types';
|
import { QuickFiltersSource, SignalType } from 'components/QuickFilters/types';
|
||||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||||
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import LogExplorerQuerySection from 'container/LogExplorerQuerySection';
|
import LogExplorerQuerySection from 'container/LogExplorerQuerySection';
|
||||||
import LogsExplorerViews from 'container/LogsExplorerViews';
|
import LogsExplorerViewsContainer from 'container/LogsExplorerViews';
|
||||||
import {
|
import {
|
||||||
defaultLogsSelectedColumns,
|
defaultLogsSelectedColumns,
|
||||||
defaultOptionsQuery,
|
defaultOptionsQuery,
|
||||||
@ -20,6 +21,7 @@ import LeftToolbarActions from 'container/QueryBuilder/components/ToolbarActions
|
|||||||
import RightToolbarActions from 'container/QueryBuilder/components/ToolbarActions/RightToolbarActions';
|
import RightToolbarActions from 'container/QueryBuilder/components/ToolbarActions/RightToolbarActions';
|
||||||
import Toolbar from 'container/Toolbar/Toolbar';
|
import Toolbar from 'container/Toolbar/Toolbar';
|
||||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||||
|
import { useHandleExplorerTabChange } from 'hooks/useHandleExplorerTabChange';
|
||||||
import useUrlQueryData from 'hooks/useUrlQueryData';
|
import useUrlQueryData from 'hooks/useUrlQueryData';
|
||||||
import { isEqual, isNull } from 'lodash-es';
|
import { isEqual, isNull } from 'lodash-es';
|
||||||
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
|
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
|
||||||
@ -28,13 +30,11 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|||||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
import { DataSource } from 'types/common/queryBuilder';
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
|
|
||||||
import { WrapperStyled } from './styles';
|
import { ExplorerViews } from './utils';
|
||||||
import { SELECTED_VIEWS } from './utils';
|
|
||||||
|
|
||||||
function LogsExplorer(): JSX.Element {
|
function LogsExplorer(): JSX.Element {
|
||||||
const [showFrequencyChart, setShowFrequencyChart] = useState(true);
|
const [selectedView, setSelectedView] = useState<ExplorerViews>(
|
||||||
const [selectedView, setSelectedView] = useState<SELECTED_VIEWS>(
|
ExplorerViews.LIST,
|
||||||
SELECTED_VIEWS.QUERY_BUILDER_V2,
|
|
||||||
);
|
);
|
||||||
const { preferences, loading: preferencesLoading } = usePreferenceContext();
|
const { preferences, loading: preferencesLoading } = usePreferenceContext();
|
||||||
|
|
||||||
@ -48,7 +48,9 @@ function LogsExplorer(): JSX.Element {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
const { handleRunQuery, currentQuery } = useQueryBuilder();
|
const { handleRunQuery, handleSetConfig } = useQueryBuilder();
|
||||||
|
|
||||||
|
const { handleExplorerTabChange } = useHandleExplorerTabChange();
|
||||||
|
|
||||||
const listQueryKeyRef = useRef<any>();
|
const listQueryKeyRef = useRef<any>();
|
||||||
|
|
||||||
@ -56,13 +58,19 @@ function LogsExplorer(): JSX.Element {
|
|||||||
|
|
||||||
const [isLoadingQueries, setIsLoadingQueries] = useState<boolean>(false);
|
const [isLoadingQueries, setIsLoadingQueries] = useState<boolean>(false);
|
||||||
|
|
||||||
const handleToggleShowFrequencyChart = (): void => {
|
const handleChangeSelectedView = useCallback(
|
||||||
setShowFrequencyChart(!showFrequencyChart);
|
(view: ExplorerViews): void => {
|
||||||
};
|
if (selectedView === ExplorerViews.LIST) {
|
||||||
|
handleSetConfig(PANEL_TYPES.LIST, DataSource.LOGS);
|
||||||
|
}
|
||||||
|
|
||||||
const handleChangeSelectedView = (view: SELECTED_VIEWS): void => {
|
setSelectedView(view);
|
||||||
setSelectedView(view);
|
handleExplorerTabChange(
|
||||||
};
|
view === ExplorerViews.TIMESERIES ? PANEL_TYPES.TIME_SERIES : view,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[handleSetConfig, handleExplorerTabChange, selectedView],
|
||||||
|
);
|
||||||
|
|
||||||
const handleFilterVisibilityChange = (): void => {
|
const handleFilterVisibilityChange = (): void => {
|
||||||
setLocalStorageApi(
|
setLocalStorageApi(
|
||||||
@ -72,19 +80,6 @@ function LogsExplorer(): JSX.Element {
|
|||||||
setShowFilters((prev) => !prev);
|
setShowFilters((prev) => !prev);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Switch to query builder view if there are more than 1 queries
|
|
||||||
useEffect(() => {
|
|
||||||
if (currentQuery.builder.queryData.length > 1) {
|
|
||||||
handleChangeSelectedView(SELECTED_VIEWS.QUERY_BUILDER_V2);
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
currentQuery.builder.queryData.length === 1 &&
|
|
||||||
currentQuery.builder.queryData?.[0]?.groupBy?.length > 0
|
|
||||||
) {
|
|
||||||
handleChangeSelectedView(SELECTED_VIEWS.QUERY_BUILDER_V2);
|
|
||||||
}
|
|
||||||
}, [currentQuery.builder.queryData, currentQuery.builder.queryData.length]);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
redirectWithQuery: redirectWithOptionsData,
|
redirectWithQuery: redirectWithOptionsData,
|
||||||
} = useUrlQueryData<OptionsQuery>(URL_OPTIONS, defaultOptionsQuery);
|
} = useUrlQueryData<OptionsQuery>(URL_OPTIONS, defaultOptionsQuery);
|
||||||
@ -195,42 +190,44 @@ function LogsExplorer(): JSX.Element {
|
|||||||
preferencesLoading,
|
preferencesLoading,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const isMultipleQueries = useMemo(
|
|
||||||
() =>
|
|
||||||
currentQuery.builder.queryData?.length > 1 ||
|
|
||||||
currentQuery.builder.queryFormulas?.length > 0,
|
|
||||||
[currentQuery],
|
|
||||||
);
|
|
||||||
|
|
||||||
const isGroupByPresent = useMemo(
|
|
||||||
() =>
|
|
||||||
currentQuery.builder.queryData?.length === 1 &&
|
|
||||||
currentQuery.builder.queryData?.[0]?.groupBy?.length > 0,
|
|
||||||
[currentQuery.builder.queryData],
|
|
||||||
);
|
|
||||||
|
|
||||||
const toolbarViews = useMemo(
|
const toolbarViews = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
search: {
|
list: {
|
||||||
name: 'search',
|
name: 'list',
|
||||||
label: 'Search',
|
label: 'List',
|
||||||
disabled: isMultipleQueries || isGroupByPresent,
|
|
||||||
show: true,
|
show: true,
|
||||||
|
key: 'list',
|
||||||
},
|
},
|
||||||
queryBuilder: {
|
timeseries: {
|
||||||
name: 'query-builder',
|
name: 'timeseries',
|
||||||
label: 'Query Builder',
|
label: 'Timeseries',
|
||||||
disabled: false,
|
disabled: false,
|
||||||
show: true,
|
show: true,
|
||||||
|
key: 'timeseries',
|
||||||
|
},
|
||||||
|
trace: {
|
||||||
|
name: 'trace',
|
||||||
|
label: 'Trace',
|
||||||
|
disabled: false,
|
||||||
|
show: false,
|
||||||
|
key: 'trace',
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
name: 'table',
|
||||||
|
label: 'Table',
|
||||||
|
disabled: false,
|
||||||
|
show: true,
|
||||||
|
key: 'table',
|
||||||
},
|
},
|
||||||
clickhouse: {
|
clickhouse: {
|
||||||
name: 'clickhouse',
|
name: 'clickhouse',
|
||||||
label: 'Clickhouse',
|
label: 'Clickhouse',
|
||||||
disabled: false,
|
disabled: false,
|
||||||
show: false,
|
show: false,
|
||||||
|
key: 'clickhouse',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
[isGroupByPresent, isMultipleQueries],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -256,8 +253,6 @@ function LogsExplorer(): JSX.Element {
|
|||||||
items={toolbarViews}
|
items={toolbarViews}
|
||||||
selectedView={selectedView}
|
selectedView={selectedView}
|
||||||
onChangeSelectedView={handleChangeSelectedView}
|
onChangeSelectedView={handleChangeSelectedView}
|
||||||
onToggleHistrogramVisibility={handleToggleShowFrequencyChart}
|
|
||||||
showFrequencyChart={showFrequencyChart}
|
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
rightActions={
|
rightActions={
|
||||||
@ -271,24 +266,21 @@ function LogsExplorer(): JSX.Element {
|
|||||||
showOldCTA
|
showOldCTA
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<WrapperStyled>
|
<div className="log-explorer-query-container">
|
||||||
<div className="log-explorer-query-container">
|
<div>
|
||||||
<div>
|
<ExplorerCard sourcepage={DataSource.LOGS}>
|
||||||
<ExplorerCard sourcepage={DataSource.LOGS}>
|
<LogExplorerQuerySection selectedView={selectedView} />
|
||||||
<LogExplorerQuerySection selectedView={selectedView} />
|
</ExplorerCard>
|
||||||
</ExplorerCard>
|
|
||||||
</div>
|
|
||||||
<div className="logs-explorer-views">
|
|
||||||
<LogsExplorerViews
|
|
||||||
selectedView={selectedView}
|
|
||||||
showFrequencyChart={showFrequencyChart}
|
|
||||||
listQueryKeyRef={listQueryKeyRef}
|
|
||||||
chartQueryKeyRef={chartQueryKeyRef}
|
|
||||||
setIsLoadingQueries={setIsLoadingQueries}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</WrapperStyled>
|
<div className="logs-explorer-views">
|
||||||
|
<LogsExplorerViewsContainer
|
||||||
|
selectedView={selectedView}
|
||||||
|
listQueryKeyRef={listQueryKeyRef}
|
||||||
|
chartQueryKeyRef={chartQueryKeyRef}
|
||||||
|
setIsLoadingQueries={setIsLoadingQueries}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</Sentry.ErrorBoundary>
|
</Sentry.ErrorBoundary>
|
||||||
|
|||||||
@ -17,11 +17,12 @@ export const prepareQueryWithDefaultTimestamp = (query: Query): Query => ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
export enum SELECTED_VIEWS {
|
export enum ExplorerViews {
|
||||||
SEARCH = 'search',
|
LIST = 'list',
|
||||||
QUERY_BUILDER = 'query-builder',
|
TIMESERIES = 'timeseries',
|
||||||
|
TRACE = 'trace',
|
||||||
|
TABLE = 'table',
|
||||||
CLICKHOUSE = 'clickhouse',
|
CLICKHOUSE = 'clickhouse',
|
||||||
QUERY_BUILDER_V2 = 'query-builder-v2',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LogsQuickFiltersConfig: IQuickFiltersConfig[] = [
|
export const LogsQuickFiltersConfig: IQuickFiltersConfig[] = [
|
||||||
|
|||||||
@ -8,11 +8,11 @@
|
|||||||
.ant-collapse-header-text {
|
.ant-collapse-header-text {
|
||||||
color: var(--bg-vanilla-400);
|
color: var(--bg-vanilla-400);
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 14px;
|
font-size: 12px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 18px;
|
line-height: 16px;
|
||||||
letter-spacing: -0.07px;
|
letter-spacing: -0.065px;
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,11 +24,11 @@
|
|||||||
.ant-input-group-addon {
|
.ant-input-group-addon {
|
||||||
color: var(--bg-vanilla-400);
|
color: var(--bg-vanilla-400);
|
||||||
font-family: 'Space Mono', monospace;
|
font-family: 'Space Mono', monospace;
|
||||||
font-size: 12px;
|
font-size: 11px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
letter-spacing: 0.48px;
|
letter-spacing: 0.44px;
|
||||||
padding: 0 6px;
|
padding: 0 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,11 +37,11 @@
|
|||||||
|
|
||||||
color: var(--bg-vanilla-400);
|
color: var(--bg-vanilla-400);
|
||||||
font-family: 'Space Mono', monospace;
|
font-family: 'Space Mono', monospace;
|
||||||
font-size: 12px;
|
font-size: 11px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
letter-spacing: 0.48px;
|
letter-spacing: 0.44px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,7 +54,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.filter-header {
|
.filter-header {
|
||||||
padding: 16px 8px 16px 12px;
|
padding: 4px 8px;
|
||||||
|
|
||||||
.filter-title {
|
.filter-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
|
|||||||
@ -1,9 +1,4 @@
|
|||||||
.trace-explorer-header {
|
.trace-explorer-header {
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
padding-left: 8px;
|
|
||||||
|
|
||||||
.trace-explorer-run-query {
|
.trace-explorer-run-query {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
@ -27,17 +22,54 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.traces-explorer-views {
|
.traces-explorer-views {
|
||||||
|
padding: 8px;
|
||||||
|
|
||||||
.ant-tabs-tabpane {
|
.ant-tabs-tabpane {
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.qb-search-view-container {
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid var(--Slate-400, #1d212d) !important;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.ant-select-selector {
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 1px solid var(--Slate-400, #1d212d) !important;
|
||||||
|
background: var(--Ink-300, #16181d) !important;
|
||||||
|
height: 34px !important;
|
||||||
|
box-sizing: border-box !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.trace-explorer-list-view {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trace-explorer-traces-view {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trace-explorer-table-view {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trace-explorer-time-series-view {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.trace-explorer-page {
|
.trace-explorer-page {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
.filter {
|
.filter {
|
||||||
width: 260px;
|
width: 260px;
|
||||||
height: 100vh;
|
height: 100%;
|
||||||
|
min-height: 100vh;
|
||||||
|
|
||||||
border-right: 0px;
|
border-right: 0px;
|
||||||
border: 1px solid var(--bg-slate-400);
|
border: 1px solid var(--bg-slate-400);
|
||||||
|
|||||||
@ -1,12 +1,10 @@
|
|||||||
import './TracesExplorer.styles.scss';
|
import './TracesExplorer.styles.scss';
|
||||||
|
|
||||||
import { FilterOutlined } from '@ant-design/icons';
|
|
||||||
import * as Sentry from '@sentry/react';
|
import * as Sentry from '@sentry/react';
|
||||||
import { Button, Card, Tabs, Tooltip } from 'antd';
|
import { Card } from 'antd';
|
||||||
import logEvent from 'api/common/logEvent';
|
import logEvent from 'api/common/logEvent';
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import ExplorerCard from 'components/ExplorerCard/ExplorerCard';
|
import ExplorerCard from 'components/ExplorerCard/ExplorerCard';
|
||||||
import QueryBuilderV2 from 'components/QueryBuilderV2/QueryBuilderV2';
|
|
||||||
import QuickFilters from 'components/QuickFilters/QuickFilters';
|
import QuickFilters from 'components/QuickFilters/QuickFilters';
|
||||||
import { QuickFiltersSource, SignalType } from 'components/QuickFilters/types';
|
import { QuickFiltersSource, SignalType } from 'components/QuickFilters/types';
|
||||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||||
@ -15,10 +13,16 @@ import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
|
|||||||
import ExplorerOptionWrapper from 'container/ExplorerOptions/ExplorerOptionWrapper';
|
import ExplorerOptionWrapper from 'container/ExplorerOptions/ExplorerOptionWrapper';
|
||||||
import ExportPanel from 'container/ExportPanel';
|
import ExportPanel from 'container/ExportPanel';
|
||||||
import { useOptionsMenu } from 'container/OptionsMenu';
|
import { useOptionsMenu } from 'container/OptionsMenu';
|
||||||
|
import LeftToolbarActions from 'container/QueryBuilder/components/ToolbarActions/LeftToolbarActions';
|
||||||
import RightToolbarActions from 'container/QueryBuilder/components/ToolbarActions/RightToolbarActions';
|
import RightToolbarActions from 'container/QueryBuilder/components/ToolbarActions/RightToolbarActions';
|
||||||
import DateTimeSelector from 'container/TopNav/DateTimeSelectionV2';
|
import TimeSeriesView from 'container/TimeSeriesView';
|
||||||
|
import Toolbar from 'container/Toolbar/Toolbar';
|
||||||
|
import ListView from 'container/TracesExplorer/ListView';
|
||||||
|
// import DateTimeSelector from 'container/TopNav/DateTimeSelectionV2';
|
||||||
import { defaultSelectedColumns } from 'container/TracesExplorer/ListView/configs';
|
import { defaultSelectedColumns } from 'container/TracesExplorer/ListView/configs';
|
||||||
import QuerySection from 'container/TracesExplorer/QuerySection';
|
import QuerySection from 'container/TracesExplorer/QuerySection';
|
||||||
|
import TableView from 'container/TracesExplorer/TableView';
|
||||||
|
import TracesView from 'container/TracesExplorer/TracesView';
|
||||||
import { useUpdateDashboard } from 'hooks/dashboard/useUpdateDashboard';
|
import { useUpdateDashboard } from 'hooks/dashboard/useUpdateDashboard';
|
||||||
import { addEmptyWidgetInDashboardJSONWithQuery } from 'hooks/dashboard/utils';
|
import { addEmptyWidgetInDashboardJSONWithQuery } from 'hooks/dashboard/utils';
|
||||||
import { useGetPanelTypesQueryParam } from 'hooks/queryBuilder/useGetPanelTypesQueryParam';
|
import { useGetPanelTypesQueryParam } from 'hooks/queryBuilder/useGetPanelTypesQueryParam';
|
||||||
@ -35,9 +39,6 @@ import { DataSource } from 'types/common/queryBuilder';
|
|||||||
import { generateExportToDashboardLink } from 'utils/dashboard/generateExportToDashboardLink';
|
import { generateExportToDashboardLink } from 'utils/dashboard/generateExportToDashboardLink';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { ActionsWrapper, Container } from './styles';
|
|
||||||
import { getTabsItems } from './utils';
|
|
||||||
|
|
||||||
function TracesExplorer(): JSX.Element {
|
function TracesExplorer(): JSX.Element {
|
||||||
const {
|
const {
|
||||||
currentQuery,
|
currentQuery,
|
||||||
@ -57,12 +58,11 @@ function TracesExplorer(): JSX.Element {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const currentPanelType = useGetPanelTypesQueryParam();
|
const currentPanelType = useGetPanelTypesQueryParam();
|
||||||
|
const currentTab = panelType || PANEL_TYPES.LIST;
|
||||||
|
|
||||||
const { handleExplorerTabChange } = useHandleExplorerTabChange();
|
const { handleExplorerTabChange } = useHandleExplorerTabChange();
|
||||||
const { safeNavigate } = useSafeNavigate();
|
const { safeNavigate } = useSafeNavigate();
|
||||||
|
|
||||||
const currentTab = panelType || PANEL_TYPES.LIST;
|
|
||||||
|
|
||||||
const listQuery = useMemo(() => {
|
const listQuery = useMemo(() => {
|
||||||
if (!stagedQuery || stagedQuery.builder.queryData.length < 1) return null;
|
if (!stagedQuery || stagedQuery.builder.queryData.length < 1) return null;
|
||||||
|
|
||||||
@ -106,11 +106,6 @@ function TracesExplorer(): JSX.Element {
|
|||||||
};
|
};
|
||||||
}, [updateAllQueriesOperators]);
|
}, [updateAllQueriesOperators]);
|
||||||
|
|
||||||
const tabsItems = getTabsItems({
|
|
||||||
isListViewDisabled: isMultipleQueries || isGroupByExist,
|
|
||||||
isFilterApplied: !isEmpty(listQuery?.filters.items),
|
|
||||||
});
|
|
||||||
|
|
||||||
const exportDefaultQuery = useMemo(
|
const exportDefaultQuery = useMemo(
|
||||||
() =>
|
() =>
|
||||||
updateAllQueriesOperators(
|
updateAllQueriesOperators(
|
||||||
@ -184,8 +179,10 @@ function TracesExplorer(): JSX.Element {
|
|||||||
handleExplorerTabChange,
|
handleExplorerTabChange,
|
||||||
currentPanelType,
|
currentPanelType,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const [isOpen, setOpen] = useState<boolean>(true);
|
const [isOpen, setOpen] = useState<boolean>(true);
|
||||||
const logEventCalledRef = useRef(false);
|
const logEventCalledRef = useRef(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!logEventCalledRef.current) {
|
if (!logEventCalledRef.current) {
|
||||||
logEvent('Traces Explorer: Page visited', {});
|
logEvent('Traces Explorer: Page visited', {});
|
||||||
@ -193,6 +190,50 @@ function TracesExplorer(): JSX.Element {
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const toolbarViews = useMemo(
|
||||||
|
() => ({
|
||||||
|
list: {
|
||||||
|
name: 'list',
|
||||||
|
label: 'List',
|
||||||
|
show: true,
|
||||||
|
key: 'list',
|
||||||
|
},
|
||||||
|
timeseries: {
|
||||||
|
name: 'timeseries',
|
||||||
|
label: 'Timeseries',
|
||||||
|
disabled: false,
|
||||||
|
show: true,
|
||||||
|
key: 'timeseries',
|
||||||
|
},
|
||||||
|
trace: {
|
||||||
|
name: 'trace',
|
||||||
|
label: 'Trace',
|
||||||
|
disabled: false,
|
||||||
|
show: true,
|
||||||
|
key: 'trace',
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
name: 'table',
|
||||||
|
label: 'Table',
|
||||||
|
disabled: false,
|
||||||
|
show: true,
|
||||||
|
key: 'table',
|
||||||
|
},
|
||||||
|
clickhouse: {
|
||||||
|
name: 'clickhouse',
|
||||||
|
label: 'Clickhouse',
|
||||||
|
disabled: false,
|
||||||
|
show: false,
|
||||||
|
key: 'clickhouse',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const isFilterApplied = useMemo(() => !isEmpty(listQuery?.filters.items), [
|
||||||
|
listQuery,
|
||||||
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sentry.ErrorBoundary fallback={<ErrorBoundaryFallback />}>
|
<Sentry.ErrorBoundary fallback={<ErrorBoundaryFallback />}>
|
||||||
<div className="trace-explorer-page">
|
<div className="trace-explorer-page">
|
||||||
@ -206,55 +247,87 @@ function TracesExplorer(): JSX.Element {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
<Card
|
<div
|
||||||
className={cx('trace-explorer', {
|
className={cx('trace-explorer', {
|
||||||
'filters-expanded': isOpen,
|
'filters-expanded': isOpen,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<div className={`trace-explorer-header ${isOpen ? 'single-child' : ''}`}>
|
<div className="trace-explorer-header">
|
||||||
{!isOpen && (
|
<Toolbar
|
||||||
<Tooltip title="Expand filters" placement="right">
|
showAutoRefresh
|
||||||
<Button
|
leftActions={
|
||||||
onClick={(): void => setOpen(!isOpen)}
|
<LeftToolbarActions
|
||||||
className="filter-outlined-btn"
|
showFilter={isOpen}
|
||||||
data-testid="filter-uncollapse-btn"
|
handleFilterVisibilityChange={(): void => setOpen(!isOpen)}
|
||||||
>
|
items={toolbarViews}
|
||||||
<FilterOutlined />
|
selectedView={
|
||||||
</Button>
|
currentTab === PANEL_TYPES.TIME_SERIES ? 'timeseries' : currentTab
|
||||||
</Tooltip>
|
}
|
||||||
)}
|
onChangeSelectedView={(view): void => {
|
||||||
<div className="trace-explorer-run-query">
|
if (view === 'timeseries') {
|
||||||
<RightToolbarActions onStageRunQuery={handleRunQuery} />
|
handleExplorerTabChange(PANEL_TYPES.TIME_SERIES);
|
||||||
<DateTimeSelector showAutoRefresh />
|
// setSelectedView(PANEL_TYPES.TIME_SERIES);
|
||||||
</div>
|
} else {
|
||||||
|
handleExplorerTabChange((view as unknown) as PANEL_TYPES);
|
||||||
|
// setSelectedView((view as unknown) as PANEL_TYPES);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
rightActions={<RightToolbarActions onStageRunQuery={handleRunQuery} />}
|
||||||
|
// showOldCTA={false}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ExplorerCard sourcepage={DataSource.TRACES}>
|
<ExplorerCard sourcepage={DataSource.TRACES}>
|
||||||
{/* <QuerySection /> */}
|
<div className="query-section-container">
|
||||||
<QueryBuilderV2
|
<QuerySection selectedView={currentTab} />
|
||||||
source={DataSource.TRACES}
|
</div>
|
||||||
query={currentQuery.builder.queryData[0]}
|
|
||||||
/>
|
|
||||||
</ExplorerCard>
|
</ExplorerCard>
|
||||||
|
|
||||||
<Container className="traces-explorer-views">
|
<div className="traces-explorer-views">
|
||||||
<ActionsWrapper>
|
<div className="traces-explorer-export-panel">
|
||||||
<ExportPanel query={exportDefaultQuery} onExport={handleExport} />
|
<ExportPanel
|
||||||
</ActionsWrapper>
|
query={exportDefaultQuery}
|
||||||
|
isLoading={false}
|
||||||
|
onExport={handleExport}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{currentTab === PANEL_TYPES.LIST && (
|
||||||
|
<div className="trace-explorer-list-view">
|
||||||
|
<ListView isFilterApplied={isFilterApplied} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{currentTab === PANEL_TYPES.TRACE && (
|
||||||
|
<div className="trace-explorer-traces-view">
|
||||||
|
<TracesView isFilterApplied={isFilterApplied} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{currentTab === PANEL_TYPES.TIME_SERIES && (
|
||||||
|
<div className="trace-explorer-time-series-view">
|
||||||
|
<TimeSeriesView
|
||||||
|
dataSource={DataSource.TRACES}
|
||||||
|
isFilterApplied={isFilterApplied}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{currentTab === PANEL_TYPES.TABLE && (
|
||||||
|
<div className="trace-explorer-table-view">
|
||||||
|
<TableView />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<Tabs
|
|
||||||
defaultActiveKey={currentTab}
|
|
||||||
activeKey={currentTab}
|
|
||||||
items={tabsItems}
|
|
||||||
onChange={handleExplorerTabChange}
|
|
||||||
/>
|
|
||||||
</Container>
|
|
||||||
<ExplorerOptionWrapper
|
<ExplorerOptionWrapper
|
||||||
disabled={!stagedQuery}
|
disabled={!stagedQuery}
|
||||||
query={exportDefaultQuery}
|
query={exportDefaultQuery}
|
||||||
sourcepage={DataSource.TRACES}
|
sourcepage={DataSource.TRACES}
|
||||||
onExport={handleExport}
|
onExport={handleExport}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Sentry.ErrorBoundary>
|
</Sentry.ErrorBoundary>
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user