Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/components/MetricChart/MetricChart.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,21 @@
display: flex;
flex-direction: column;

padding: 16px 16px 8px;
padding: var(--g-spacing-4) var(--g-spacing-4) var(--g-spacing-2);

border: 1px solid var(--g-color-line-generic);
border-radius: 8px;

&_noBorder {
padding: 0;

border: none;
}

&_fullWidth {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do you need it here? In components you pass width directly via styles property.

width: 100%;
}

&__title {
margin-bottom: 10px;
}
Expand Down
44 changes: 40 additions & 4 deletions src/components/MetricChart/MetricChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ import React from 'react';
import ChartKit, {settings} from '@gravity-ui/chartkit';
import type {YagrWidgetData} from '@gravity-ui/chartkit/yagr';
import {YagrPlugin} from '@gravity-ui/chartkit/yagr';
import {Flex} from '@gravity-ui/uikit';

import {cn} from '../../utils/cn';
import type {TimeFrame} from '../../utils/timeframes';
import {ResponseError} from '../Errors/ResponseError';
import {Loader} from '../Loader';
import {TimeFrameDropdown} from '../TimeFrameDropdown/TimeFrameDropdown';
import {TimeFrameSelector} from '../TimeFrameSelector/TimeFrameSelector';

import {colorToRGBA, colors} from './colors';
import {getDefaultDataFormatter} from './getDefaultDataFormatter';
Expand Down Expand Up @@ -122,6 +125,21 @@ interface DiagnosticsChartProps {
* Pass isChartVisible prop to ensure proper chart render
*/
isChartVisible?: boolean;

/** Remove border from chart */
noBorder?: boolean;

/** Make chart take full width of container */
fullWidth?: boolean;

/** Show timeframe selector to the right of chart title */
withTimeframeSelector?: boolean;

/** Callback when timeframe is changed via the selector */
onTimeFrameChange?: (timeFrame: TimeFrame) => void;

/** Timeframe component to choose between 'selector' and 'dropdown' */
timeFrameComponent?: 'selector' | 'dropdown';
}

export const MetricChart = ({
Expand All @@ -135,7 +153,16 @@ export const MetricChart = ({
chartOptions,
onChartDataStatusChange,
isChartVisible,
noBorder,
fullWidth,
withTimeframeSelector,
onTimeFrameChange,
timeFrameComponent = 'selector',
}: DiagnosticsChartProps) => {
// Use a reasonable default for maxDataPoints when fullWidth is true
const effectiveWidth = fullWidth ? 600 : width;
const maxDataPoints = effectiveWidth / 2;

const {currentData, error, isFetching, status} = chartApi.useGetChartDataQuery(
// maxDataPoints param is calculated based on width
// should be width > maxDataPoints to prevent points that cannot be selected
Expand All @@ -144,7 +171,7 @@ export const MetricChart = ({
database,
metrics,
timeFrame,
maxDataPoints: width / 2,
maxDataPoints,
},
{pollingInterval: autorefresh},
);
Expand Down Expand Up @@ -176,13 +203,22 @@ export const MetricChart = ({

return (
<div
className={b(null)}
className={b({noBorder, fullWidth})}
style={{
height,
width,
width: fullWidth ? '100%' : width,
}}
>
<div className={b('title')}>{title}</div>
<Flex className={b('title')} justifyContent="space-between" alignItems="center">
<div>{title}</div>
{withTimeframeSelector &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do u think about doing a prop like renderChartToolbar and pass whatever user of this component needs?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think its overengineering =)

Copy link
Collaborator Author

@astandrik astandrik Jul 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but why not ¯\_(ツ)_/¯

onTimeFrameChange &&
(timeFrameComponent === 'dropdown' ? (
<TimeFrameDropdown value={timeFrame} onChange={onTimeFrameChange} />
) : (
<TimeFrameSelector value={timeFrame} onChange={onTimeFrameChange} />
))}
</Flex>
{renderContent()}
</div>
);
Expand Down
105 changes: 105 additions & 0 deletions src/components/QueriesActivityBar/QueriesActivityBar.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
@use '../../styles/mixins.scss';

.queries-activity-bar {
$b: &;

margin-bottom: var(--diagnostics-section-title-margin);

border: 1px solid transparent;
border-radius: var(--g-border-radius-m);

// Collapsed state (default)
background-color: var(--g-color-base-float);

&_expanded {
border: 1px solid var(--g-color-base-generic);
border-radius: var(--g-border-radius-m);
background-color: transparent;
}

&__disclosure {
width: 100%;
}

&__header {
display: flex;
justify-content: space-between;
align-items: center;
gap: var(--g-spacing-3);

padding: var(--g-spacing-3) var(--g-spacing-4);

cursor: pointer;

border-radius: var(--g-border-radius-m);

transition: background-color 0.15s ease;

&:hover {
background-color: var(--g-color-base-simple-hover);
}

// When expanded, only round top corners
#{$b}_expanded &:hover {
background-color: transparent;
}
}

&__content-wrapper {
display: flex;
flex-grow: 1;
align-items: center;
gap: var(--g-spacing-2);
}

&__metrics {
display: flex;
align-items: center;
gap: var(--g-spacing-1);
}

&__content {
display: flex;
flex-direction: column;
gap: var(--g-spacing-4);
}

&__stats {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--g-spacing-1);

padding: 0 var(--g-spacing-4);
}

&__open-queries-button {
margin-left: 4px;
}

&__charts {
display: flex;
gap: var(--g-spacing-4);

padding: 0 var(--g-spacing-4);
padding-top: var(--g-spacing-4);

@media (max-width: 1200px) {
flex-direction: column;
}
}

&__chart-container {
display: flex;
flex: 1;
flex-direction: column;
gap: var(--g-spacing-3);
}

// Focus states for accessibility
&__header:focus-visible,
&__open-queries-button:focus-visible {
outline: 2px solid var(--g-color-line-focus);
outline-offset: 2px;
}
}
Loading
Loading