Compare commits

...

1 Commits

Author SHA1 Message Date
Abhi kumar
c5ef455283 fix: added fix for panel setting scrollbar issue (#10587)
Some checks are pending
build-staging / prepare (push) Waiting to run
build-staging / js-build (push) Blocked by required conditions
build-staging / go-build (push) Blocked by required conditions
build-staging / staging (push) Blocked by required conditions
Release Drafter / update_release_draft (push) Waiting to run
* fix: added fix for panel setting scrollbar issue

* fix: added changes for panel switch
2026-03-13 19:30:49 +00:00
5 changed files with 86 additions and 80 deletions

View File

@@ -1,6 +1,7 @@
.right-container {
display: flex;
flex-direction: column;
padding-bottom: 48px;
.header {
display: flex;

View File

@@ -835,56 +835,54 @@ function NewWidget({
</LeftContainerWrapper>
<RightContainerWrapper>
<OverlayScrollbar>
<RightContainer
setGraphHandler={setGraphHandler}
title={title}
setTitle={setTitle}
description={description}
setDescription={setDescription}
stackedBarChart={stackedBarChart}
setStackedBarChart={setStackedBarChart}
opacity={opacity}
yAxisUnit={yAxisUnit}
columnUnits={columnUnits}
setColumnUnits={setColumnUnits}
bucketCount={bucketCount}
bucketWidth={bucketWidth}
combineHistogram={combineHistogram}
setCombineHistogram={setCombineHistogram}
setBucketWidth={setBucketWidth}
setBucketCount={setBucketCount}
setOpacity={setOpacity}
selectedNullZeroValue={selectedNullZeroValue}
setSelectedNullZeroValue={setSelectedNullZeroValue}
selectedGraph={graphType}
setSelectedTime={setSelectedTime}
selectedTime={selectedTime}
setYAxisUnit={setYAxisUnit}
decimalPrecision={decimalPrecision}
setDecimalPrecision={setDecimalPrecision}
thresholds={thresholds}
setThresholds={setThresholds}
selectedWidget={selectedWidget}
isFillSpans={isFillSpans}
setIsFillSpans={setIsFillSpans}
isLogScale={isLogScale}
setIsLogScale={setIsLogScale}
legendPosition={legendPosition}
setLegendPosition={setLegendPosition}
customLegendColors={customLegendColors}
setCustomLegendColors={setCustomLegendColors}
queryResponse={queryResponse}
softMin={softMin}
setSoftMin={setSoftMin}
softMax={softMax}
setSoftMax={setSoftMax}
contextLinks={contextLinks}
setContextLinks={setContextLinks}
enableDrillDown={enableDrillDown}
isNewDashboard={isNewDashboard}
/>
</OverlayScrollbar>
<RightContainer
setGraphHandler={setGraphHandler}
title={title}
setTitle={setTitle}
description={description}
setDescription={setDescription}
stackedBarChart={stackedBarChart}
setStackedBarChart={setStackedBarChart}
opacity={opacity}
yAxisUnit={yAxisUnit}
columnUnits={columnUnits}
setColumnUnits={setColumnUnits}
bucketCount={bucketCount}
bucketWidth={bucketWidth}
combineHistogram={combineHistogram}
setCombineHistogram={setCombineHistogram}
setBucketWidth={setBucketWidth}
setBucketCount={setBucketCount}
setOpacity={setOpacity}
selectedNullZeroValue={selectedNullZeroValue}
setSelectedNullZeroValue={setSelectedNullZeroValue}
selectedGraph={graphType}
setSelectedTime={setSelectedTime}
selectedTime={selectedTime}
setYAxisUnit={setYAxisUnit}
decimalPrecision={decimalPrecision}
setDecimalPrecision={setDecimalPrecision}
thresholds={thresholds}
setThresholds={setThresholds}
selectedWidget={selectedWidget}
isFillSpans={isFillSpans}
setIsFillSpans={setIsFillSpans}
isLogScale={isLogScale}
setIsLogScale={setIsLogScale}
legendPosition={legendPosition}
setLegendPosition={setLegendPosition}
customLegendColors={customLegendColors}
setCustomLegendColors={setCustomLegendColors}
queryResponse={queryResponse}
softMin={softMin}
setSoftMin={setSoftMin}
softMax={softMax}
setSoftMax={setSoftMax}
contextLinks={contextLinks}
setContextLinks={setContextLinks}
enableDrillDown={enableDrillDown}
isNewDashboard={isNewDashboard}
/>
</RightContainerWrapper>
</PanelContainer>
<Modal

View File

@@ -15,7 +15,14 @@ export const RightContainerWrapper = styled(Col)`
overflow-y: auto;
}
&::-webkit-scrollbar {
width: 0rem;
width: 0.3rem;
}
&::-webkit-scrollbar-thumb {
background: rgb(136, 136, 136);
border-radius: 0.625rem;
}
&::-webkit-scrollbar-track {
background: transparent;
}
`;

View File

@@ -1,4 +1,5 @@
import { Route } from 'react-router-dom';
import * as getDashboardModule from 'api/v1/dashboards/id/get';
import { PANEL_TYPES } from 'constants/queryBuilder';
import { rest, server } from 'mocks-server/server';
import { render, screen, waitFor } from 'tests/test-utils';
@@ -47,35 +48,33 @@ jest.mock('container/NewWidget', () => ({
default: (): JSX.Element => <div data-testid="new-widget">NewWidget</div>,
}));
// nuqs's useQueryState doesn't read from MemoryRouter, so we mock it to return
// controlled values via the `mockQueryState` map below.
const mockQueryState: Record<string, string | null> = {};
jest.mock('nuqs', () => ({
...jest.requireActual('nuqs'),
useQueryState: (key: string): [string | null, jest.Mock] => [
mockQueryState[key] ?? null,
jest.fn(),
],
}));
// Wrap component in a Route so useParams can resolve dashboardId
// Wrap component in a Route so useParams can resolve dashboardId.
// Query params are passed via the URL so useUrlQuery (react-router) can read them.
function renderAtRoute(
queryState: Record<string, string | null> = {},
): ReturnType<typeof render> {
Object.assign(mockQueryState, queryState);
const params = new URLSearchParams();
Object.entries(queryState).forEach(([k, v]) => {
if (v !== null) {
params.set(k, v);
}
});
const search = params.toString() ? `?${params.toString()}` : '';
return render(
<Route path="/dashboard/:dashboardId/new">
<DashboardWidget />
</Route>,
undefined,
{ initialRoute: `/dashboard/${DASHBOARD_ID}/new` },
{ initialRoute: `/dashboard/${DASHBOARD_ID}/new${search}` },
);
}
beforeEach(() => {
mockSafeNavigate.mockClear();
Object.keys(mockQueryState).forEach((k) => delete mockQueryState[k]);
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('DashboardWidget', () => {
@@ -102,12 +101,10 @@ describe('DashboardWidget', () => {
});
it('shows spinner while dashboard is loading', () => {
server.use(
rest.get(
`http://localhost/api/v1/dashboards/${DASHBOARD_ID}`,
(_req, res, ctx) => res(ctx.delay('infinite')),
),
);
// Spy instead of MSW delay('infinite') to avoid leaving an open network handle.
jest
.spyOn(getDashboardModule, 'default')
.mockReturnValue(new Promise(() => {}));
renderAtRoute({ widgetId: WIDGET_ID, graphType: PANEL_TYPES.TIME_SERIES });

View File

@@ -1,10 +1,11 @@
import { useEffect, useState } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { useQuery } from 'react-query';
import { generatePath, useParams } from 'react-router-dom';
import { Card, Typography } from 'antd';
import getDashboard from 'api/v1/dashboards/id/get';
import Spinner from 'components/Spinner';
import { SOMETHING_WENT_WRONG } from 'constants/api';
import { QueryParams } from 'constants/query';
import { PANEL_TYPES } from 'constants/queryBuilder';
import { DASHBOARD_CACHE_TIME } from 'constants/queryCacheTime';
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
@@ -13,7 +14,7 @@ import NewWidget from 'container/NewWidget';
import { isDrilldownEnabled } from 'container/QueryTable/Drilldown/drilldownUtils';
import { useTransformDashboardVariables } from 'hooks/dashboard/useTransformDashboardVariables';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { parseAsStringEnum, useQueryState } from 'nuqs';
import useUrlQuery from 'hooks/useUrlQuery';
import { setDashboardVariablesStore } from 'providers/Dashboard/store/dashboardVariables/dashboardVariablesStore';
import { Dashboard } from 'types/api/dashboard/getAll';
@@ -21,11 +22,13 @@ function DashboardWidget(): JSX.Element | null {
const { dashboardId } = useParams<{
dashboardId: string;
}>();
const [widgetId] = useQueryState('widgetId');
const [graphType] = useQueryState(
'graphType',
parseAsStringEnum<PANEL_TYPES>(Object.values(PANEL_TYPES)),
);
const query = useUrlQuery();
const { graphType, widgetId } = useMemo(() => {
return {
graphType: query.get(QueryParams.graphType) as PANEL_TYPES,
widgetId: query.get(QueryParams.widgetId),
};
}, [query]);
const { safeNavigate } = useSafeNavigate();