mirror of
https://github.com/grafana/grafana.git
synced 2025-02-10 07:35:45 -06:00
Remove return to panel button and related code (#45018)
This commit is contained in:
parent
834d11691f
commit
4e38ac9cf7
@ -9,7 +9,6 @@ export interface ExploreUrlState<T extends DataQuery = AnyQuery> {
|
||||
datasource: string;
|
||||
queries: T[];
|
||||
range: RawTimeRange;
|
||||
originPanelId?: number;
|
||||
context?: string;
|
||||
panelsState?: ExplorePanelsState;
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ const DEFAULT_EXPLORE_STATE: ExploreUrlState = {
|
||||
datasource: '',
|
||||
queries: [],
|
||||
range: DEFAULT_RANGE,
|
||||
originPanelId: undefined,
|
||||
};
|
||||
|
||||
describe('state functions', () => {
|
||||
|
@ -103,7 +103,7 @@ export async function getExploreUrl(args: GetExploreUrlArguments): Promise<strin
|
||||
};
|
||||
}
|
||||
|
||||
const exploreState = JSON.stringify({ ...state, originPanelId: panel.id });
|
||||
const exploreState = JSON.stringify(state);
|
||||
url = urlUtil.renderUrl('/explore', { left: exploreState });
|
||||
}
|
||||
|
||||
@ -223,7 +223,6 @@ export function parseUrlState(initial: string | undefined): ExploreUrlState {
|
||||
queries: [],
|
||||
range: DEFAULT_RANGE,
|
||||
mode: null,
|
||||
originPanelId: null,
|
||||
};
|
||||
|
||||
if (!parsed) {
|
||||
@ -245,13 +244,10 @@ export function parseUrlState(initial: string | undefined): ExploreUrlState {
|
||||
};
|
||||
const datasource = parsed[ParseUrlStateIndex.Datasource];
|
||||
const parsedSegments = parsed.slice(ParseUrlStateIndex.SegmentsStart);
|
||||
const queries = parsedSegments.filter(
|
||||
(segment) => !isSegment(segment, 'ui', 'originPanelId', 'mode', '__panelsState')
|
||||
);
|
||||
const queries = parsedSegments.filter((segment) => !isSegment(segment, 'ui', 'mode', '__panelsState'));
|
||||
|
||||
const originPanelId = parsedSegments.find((segment) => isSegment(segment, 'originPanelId'));
|
||||
const panelsState = parsedSegments.find((segment) => isSegment(segment, '__panelsState'))?.__panelsState;
|
||||
return { datasource, queries, range, originPanelId, panelsState };
|
||||
return { datasource, queries, range, panelsState };
|
||||
}
|
||||
|
||||
export function generateKey(index = 0): string {
|
||||
|
@ -117,7 +117,6 @@ function describeInitScenario(description: string, scenarioFn: ScenarioFn) {
|
||||
user: {},
|
||||
explore: {
|
||||
left: {
|
||||
originPanelId: undefined,
|
||||
queries: [],
|
||||
},
|
||||
},
|
||||
@ -230,7 +229,6 @@ describeInitScenario('Initializing existing dashboard', (ctx) => {
|
||||
|
||||
ctx.setup(() => {
|
||||
ctx.storeState.user.orgId = 12;
|
||||
ctx.storeState.explore.left.originPanelId = 2;
|
||||
ctx.storeState.explore.left.queries = mockQueries;
|
||||
});
|
||||
|
||||
|
@ -8,7 +8,6 @@ import { keybindingSrv } from 'app/core/services/keybindingSrv';
|
||||
// Actions
|
||||
import { notifyApp } from 'app/core/actions';
|
||||
import {
|
||||
clearDashboardQueriesToUpdateOnLoad,
|
||||
dashboardInitCompleted,
|
||||
dashboardInitFailed,
|
||||
dashboardInitFetching,
|
||||
@ -18,7 +17,7 @@ import {
|
||||
// Types
|
||||
import { DashboardDTO, DashboardInitPhase, DashboardRoutes, StoreState, ThunkDispatch, ThunkResult } from 'app/types';
|
||||
import { DashboardModel } from './DashboardModel';
|
||||
import { DataQuery, locationUtil, setWeekStart } from '@grafana/data';
|
||||
import { locationUtil, setWeekStart } from '@grafana/data';
|
||||
import { initVariablesTransaction } from '../../variables/state/actions';
|
||||
import { emitDashboardViewEvent } from './analyticsProcessor';
|
||||
import { dashboardWatcher } from 'app/features/live/dashboard/dashboardWatcher';
|
||||
@ -156,11 +155,6 @@ export function initDashboard(args: InitDashboardArgs): ThunkResult<void> {
|
||||
|
||||
timeSrv.init(dashboard);
|
||||
|
||||
if (storeState.dashboard.modifiedQueries) {
|
||||
const { panelId, queries } = storeState.dashboard.modifiedQueries;
|
||||
dashboard.meta.fromExplore = !!(panelId && queries);
|
||||
}
|
||||
|
||||
// template values service needs to initialize completely before the rest of the dashboard can load
|
||||
await dispatch(initVariablesTransaction(args.urlUid!, dashboard));
|
||||
|
||||
@ -195,11 +189,6 @@ export function initDashboard(args: InitDashboardArgs): ThunkResult<void> {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
if (storeState.dashboard.modifiedQueries) {
|
||||
const { panelId, queries } = storeState.dashboard.modifiedQueries;
|
||||
updateQueriesWhenComingFromExplore(dispatch, dashboard, panelId, queries);
|
||||
}
|
||||
|
||||
// send open dashboard event
|
||||
if (args.routeName !== DashboardRoutes.New) {
|
||||
emitDashboardViewEvent(dashboard);
|
||||
@ -248,19 +237,3 @@ function getNewDashboardModelData(urlFolderId?: string | null): any {
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function updateQueriesWhenComingFromExplore(
|
||||
dispatch: ThunkDispatch,
|
||||
dashboard: DashboardModel,
|
||||
originPanelId: number,
|
||||
queries: DataQuery[]
|
||||
) {
|
||||
const panelArrId = dashboard.panels.findIndex((panel) => panel.id === originPanelId);
|
||||
|
||||
if (panelArrId > -1) {
|
||||
dashboard.panels[panelArrId].targets = queries;
|
||||
}
|
||||
|
||||
// Clear update state now that we're done
|
||||
dispatch(clearDashboardQueriesToUpdateOnLoad());
|
||||
}
|
||||
|
@ -1,11 +1,5 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
import {
|
||||
DashboardAclDTO,
|
||||
DashboardInitError,
|
||||
DashboardInitPhase,
|
||||
DashboardState,
|
||||
QueriesToUpdateOnDashboardLoad,
|
||||
} from 'app/types';
|
||||
import { DashboardAclDTO, DashboardInitError, DashboardInitPhase, DashboardState } from 'app/types';
|
||||
import { AngularComponent } from '@grafana/runtime';
|
||||
import { processAclItems } from 'app/core/utils/acl';
|
||||
import { DashboardModel } from './DashboardModel';
|
||||
@ -17,7 +11,6 @@ export const initialState: DashboardState = {
|
||||
isInitSlow: false,
|
||||
getModel: () => null,
|
||||
permissions: [],
|
||||
modifiedQueries: null,
|
||||
initError: null,
|
||||
};
|
||||
|
||||
@ -55,12 +48,6 @@ const dashboardSlice = createSlice({
|
||||
state.initError = null;
|
||||
state.getModel = () => null;
|
||||
},
|
||||
setDashboardQueriesToUpdateOnLoad: (state, action: PayloadAction<QueriesToUpdateOnDashboardLoad>) => {
|
||||
state.modifiedQueries = action.payload;
|
||||
},
|
||||
clearDashboardQueriesToUpdateOnLoad: (state) => {
|
||||
state.modifiedQueries = null;
|
||||
},
|
||||
addPanel: (state, action: PayloadAction<PanelModel>) => {
|
||||
//state.panels[action.payload.id] = { pluginId: action.payload.type };
|
||||
},
|
||||
@ -90,8 +77,6 @@ export const {
|
||||
dashboardInitCompleted,
|
||||
dashboardInitServices,
|
||||
cleanUpDashboard,
|
||||
setDashboardQueriesToUpdateOnLoad,
|
||||
clearDashboardQueriesToUpdateOnLoad,
|
||||
addPanel,
|
||||
} = dashboardSlice.actions;
|
||||
|
||||
|
@ -44,8 +44,7 @@ class ExplorePaneContainerUnconnected extends React.PureComponent<Props> {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { initialized, exploreId, initialDatasource, initialQueries, initialRange, originPanelId, panelsState } =
|
||||
this.props;
|
||||
const { initialized, exploreId, initialDatasource, initialQueries, initialRange, panelsState } = this.props;
|
||||
const width = this.el?.offsetWidth ?? 0;
|
||||
|
||||
// initialize the whole explore first time we mount and if browser history contains a change in datasource
|
||||
@ -57,8 +56,7 @@ class ExplorePaneContainerUnconnected extends React.PureComponent<Props> {
|
||||
initialRange,
|
||||
width,
|
||||
this.exploreEvents,
|
||||
panelsState,
|
||||
originPanelId
|
||||
panelsState
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -103,7 +101,7 @@ function mapStateToProps(state: StoreState, props: OwnProps) {
|
||||
const timeZone = getTimeZone(state.user);
|
||||
const fiscalYearStartMonth = getFiscalYearStartMonth(state.user);
|
||||
|
||||
const { datasource, queries, range: urlRange, originPanelId, panelsState } = (urlState || {}) as ExploreUrlState;
|
||||
const { datasource, queries, range: urlRange, panelsState } = (urlState || {}) as ExploreUrlState;
|
||||
const initialDatasource = datasource || store.get(lastUsedDatasourceKeyForOrgId(state.user.orgId));
|
||||
const initialQueries: DataQuery[] = ensureQueriesMemoized(queries);
|
||||
const initialRange = urlRange
|
||||
@ -115,7 +113,6 @@ function mapStateToProps(state: StoreState, props: OwnProps) {
|
||||
initialDatasource,
|
||||
initialQueries,
|
||||
initialRange,
|
||||
originPanelId,
|
||||
panelsState,
|
||||
};
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ import { LiveTailButton } from './LiveTailButton';
|
||||
import { RunButton } from './RunButton';
|
||||
import { LiveTailControls } from './useLiveTailControls';
|
||||
import { cancelQueries, runQueries } from './state/query';
|
||||
import ReturnToDashboardButton from './ReturnToDashboardButton';
|
||||
import { isSplit } from './state/selectors';
|
||||
import { DashNavButton } from '../dashboard/components/DashNav/DashNavButton';
|
||||
|
||||
@ -102,8 +101,6 @@ class UnConnectedExploreToolbar extends PureComponent<Props> {
|
||||
].filter(Boolean)}
|
||||
>
|
||||
<ToolbarButtonRow>
|
||||
<ReturnToDashboardButton exploreId={exploreId} />
|
||||
|
||||
{!splitted ? (
|
||||
<ToolbarButton title="Split" onClick={() => split()} icon="columns" disabled={isLive}>
|
||||
Split
|
||||
|
@ -1,46 +0,0 @@
|
||||
import React, { ComponentProps } from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { UnconnectedReturnToDashboardButton as ReturnToDashboardButton } from './ReturnToDashboardButton';
|
||||
import { ExploreId } from 'app/types/explore';
|
||||
|
||||
const createProps = (propsOverride?: Partial<ComponentProps<typeof ReturnToDashboardButton>>) => {
|
||||
const defaultProps = {
|
||||
originPanelId: 1,
|
||||
splitted: false,
|
||||
canEdit: true,
|
||||
exploreId: ExploreId.left,
|
||||
queries: [],
|
||||
setDashboardQueriesToUpdateOnLoad: jest.fn(),
|
||||
};
|
||||
|
||||
return Object.assign(defaultProps, propsOverride) as ComponentProps<typeof ReturnToDashboardButton>;
|
||||
};
|
||||
|
||||
describe('ReturnToDashboardButton', () => {
|
||||
it('should render 2 buttons if originPanelId is provided', () => {
|
||||
render(<ReturnToDashboardButton {...createProps()} />);
|
||||
expect(screen.getAllByTestId(/returnButton/i)).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('should not render any button if originPanelId is not provided', () => {
|
||||
render(<ReturnToDashboardButton {...createProps({ originPanelId: undefined })} />);
|
||||
expect(screen.queryByTestId(/returnButton/i)).toBeNull();
|
||||
});
|
||||
|
||||
it('should not render any button if split view', () => {
|
||||
render(<ReturnToDashboardButton {...createProps({ splitted: true })} />);
|
||||
expect(screen.queryByTestId(/returnButton/i)).toBeNull();
|
||||
});
|
||||
|
||||
it('should not render return to panel with changes button if user cannot edit panel', () => {
|
||||
render(<ReturnToDashboardButton {...createProps({ canEdit: false })} />);
|
||||
expect(screen.getAllByTestId(/returnButton/i)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should show option to return to dashboard with changes', () => {
|
||||
render(<ReturnToDashboardButton {...createProps()} />);
|
||||
const returnWithChangesButton = screen.getByTestId('returnButtonWithChanges');
|
||||
returnWithChangesButton.click();
|
||||
expect(screen.getAllByText('Return to panel with changes')).toHaveLength(1);
|
||||
});
|
||||
});
|
@ -1,110 +0,0 @@
|
||||
import React, { FC } from 'react';
|
||||
import { connect, ConnectedProps } from 'react-redux';
|
||||
import { ButtonGroup, ButtonSelect, Icon, ToolbarButton, Tooltip } from '@grafana/ui';
|
||||
import { DataQuery, urlUtil } from '@grafana/data';
|
||||
|
||||
import kbn from '../../core/utils/kbn';
|
||||
import config from 'app/core/config';
|
||||
import { getDashboardSrv } from '../dashboard/services/DashboardSrv';
|
||||
import { StoreState } from 'app/types';
|
||||
import { ExploreId } from 'app/types/explore';
|
||||
import { setDashboardQueriesToUpdateOnLoad } from '../dashboard/state/reducers';
|
||||
import { isSplit } from './state/selectors';
|
||||
import { locationService } from '@grafana/runtime';
|
||||
import { contextSrv } from 'app/core/services/context_srv';
|
||||
|
||||
function mapStateToProps(state: StoreState, { exploreId }: { exploreId: ExploreId }) {
|
||||
const explore = state.explore;
|
||||
const splitted = isSplit(state);
|
||||
const { datasourceInstance, queries, originPanelId } = explore[exploreId]!;
|
||||
|
||||
const roles = ['Editor', 'Admin'];
|
||||
if (config.viewersCanEdit) {
|
||||
roles.push('Viewer');
|
||||
}
|
||||
|
||||
return {
|
||||
exploreId,
|
||||
datasourceInstance,
|
||||
queries,
|
||||
originPanelId,
|
||||
splitted,
|
||||
canEdit: roles.some((r) => contextSrv.hasRole(r)),
|
||||
};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
setDashboardQueriesToUpdateOnLoad,
|
||||
};
|
||||
|
||||
const connector = connect(mapStateToProps, mapDispatchToProps);
|
||||
type Props = ConnectedProps<typeof connector>;
|
||||
|
||||
export const UnconnectedReturnToDashboardButton: FC<Props> = ({
|
||||
originPanelId,
|
||||
setDashboardQueriesToUpdateOnLoad,
|
||||
queries,
|
||||
splitted,
|
||||
canEdit,
|
||||
}) => {
|
||||
const withOriginId = originPanelId && Number.isInteger(originPanelId);
|
||||
|
||||
// If in split mode, or no origin id, escape early and return null
|
||||
if (splitted || !withOriginId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const cleanQueries = (queries: DataQuery[]) => {
|
||||
return queries.map((query: DataQuery & { context?: string }) => {
|
||||
delete query.context;
|
||||
delete query.key;
|
||||
return query;
|
||||
});
|
||||
};
|
||||
|
||||
const returnToPanel = async ({ withChanges = false } = {}) => {
|
||||
const dashboardSrv = getDashboardSrv();
|
||||
const dash = dashboardSrv.getCurrent();
|
||||
if (!dash) {
|
||||
return;
|
||||
}
|
||||
|
||||
const titleSlug = kbn.slugifyForUrl(dash.title);
|
||||
|
||||
if (withChanges) {
|
||||
setDashboardQueriesToUpdateOnLoad({
|
||||
panelId: originPanelId!,
|
||||
queries: cleanQueries(queries),
|
||||
});
|
||||
}
|
||||
|
||||
const query: any = {};
|
||||
|
||||
if (withChanges || dash.panelInEdit) {
|
||||
query.editPanel = originPanelId;
|
||||
} else if (dash.panelInView) {
|
||||
query.viewPanel = originPanelId;
|
||||
}
|
||||
|
||||
locationService.push(urlUtil.renderUrl(`/d/${dash.uid}/:${titleSlug}`, query));
|
||||
};
|
||||
|
||||
return (
|
||||
<ButtonGroup>
|
||||
<Tooltip content={'Return to panel'} placement="bottom">
|
||||
<ToolbarButton data-testid="returnButton" title={'Return to panel'} onClick={() => returnToPanel()}>
|
||||
<Icon name="arrow-left" />
|
||||
</ToolbarButton>
|
||||
</Tooltip>
|
||||
{canEdit && (
|
||||
<ButtonSelect
|
||||
data-testid="returnButtonWithChanges"
|
||||
options={[{ label: 'Return to panel with changes', value: '' }]}
|
||||
onChange={() => returnToPanel({ withChanges: true })}
|
||||
/>
|
||||
)}
|
||||
</ButtonGroup>
|
||||
);
|
||||
};
|
||||
|
||||
export default connector(UnconnectedReturnToDashboardButton);
|
@ -98,7 +98,6 @@ export interface InitializeExplorePayload {
|
||||
range: TimeRange;
|
||||
history: HistoryItem[];
|
||||
datasourceInstance?: DataSourceApi;
|
||||
originPanelId?: number | null;
|
||||
}
|
||||
export const initializeExploreAction = createAction<InitializeExplorePayload>('explore/initializeExplore');
|
||||
|
||||
@ -143,9 +142,7 @@ export function initializeExplore(
|
||||
range: TimeRange,
|
||||
containerWidth: number,
|
||||
eventBridge: EventBusExtended,
|
||||
panelsState?: ExplorePanelsState,
|
||||
|
||||
originPanelId?: number | null
|
||||
panelsState?: ExplorePanelsState
|
||||
): ThunkResult<void> {
|
||||
return async (dispatch, getState) => {
|
||||
const exploreDatasources = getDataSourceSrv().getList();
|
||||
@ -166,7 +163,6 @@ export function initializeExplore(
|
||||
eventBridge,
|
||||
queries,
|
||||
range,
|
||||
originPanelId,
|
||||
datasourceInstance: instance,
|
||||
history,
|
||||
})
|
||||
@ -205,7 +201,7 @@ export function refreshExplore(exploreId: ExploreId, newUrlQuery: string): Thunk
|
||||
|
||||
const { containerWidth, eventBridge } = itemState;
|
||||
|
||||
const { datasource, queries, range: urlRange, originPanelId, panelsState } = newUrlState;
|
||||
const { datasource, queries, range: urlRange, panelsState } = newUrlState;
|
||||
const refreshQueries: DataQuery[] = [];
|
||||
|
||||
for (let index = 0; index < queries.length; index++) {
|
||||
@ -222,16 +218,7 @@ export function refreshExplore(exploreId: ExploreId, newUrlQuery: string): Thunk
|
||||
if (update.datasource) {
|
||||
const initialQueries = ensureQueries(queries);
|
||||
await dispatch(
|
||||
initializeExplore(
|
||||
exploreId,
|
||||
datasource,
|
||||
initialQueries,
|
||||
range,
|
||||
containerWidth,
|
||||
eventBridge,
|
||||
panelsState,
|
||||
originPanelId
|
||||
)
|
||||
initializeExplore(exploreId, datasource, initialQueries, range, containerWidth, eventBridge, panelsState)
|
||||
);
|
||||
return;
|
||||
}
|
||||
@ -285,7 +272,7 @@ export const paneReducer = (state: ExploreItemState = makeExplorePaneState(), ac
|
||||
}
|
||||
|
||||
if (initializeExploreAction.match(action)) {
|
||||
const { containerWidth, eventBridge, queries, range, originPanelId, datasourceInstance, history } = action.payload;
|
||||
const { containerWidth, eventBridge, queries, range, datasourceInstance, history } = action.payload;
|
||||
|
||||
return {
|
||||
...state,
|
||||
@ -295,7 +282,6 @@ export const paneReducer = (state: ExploreItemState = makeExplorePaneState(), ac
|
||||
queries,
|
||||
initialized: true,
|
||||
queryKeys: getQueryKeys(queries, datasourceInstance),
|
||||
originPanelId,
|
||||
datasourceInstance,
|
||||
history,
|
||||
datasourceMissing: !datasourceInstance,
|
||||
|
@ -237,7 +237,7 @@ export const exploreReducer = (state = initialExploreState, action: AnyAction):
|
||||
stopQueryState(rightState.querySubscription);
|
||||
}
|
||||
|
||||
if (payload.force || !Number.isInteger(state.left.originPanelId)) {
|
||||
if (payload.force) {
|
||||
return initialExploreState;
|
||||
}
|
||||
|
||||
@ -246,7 +246,6 @@ export const exploreReducer = (state = initialExploreState, action: AnyAction):
|
||||
left: {
|
||||
...initialExploreItemState,
|
||||
queries: state.left.queries,
|
||||
originPanelId: state.left.originPanelId,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ export interface DashboardMeta {
|
||||
url?: string;
|
||||
folderId?: number;
|
||||
folderUid?: string;
|
||||
fromExplore?: boolean;
|
||||
canMakeEditable?: boolean;
|
||||
submenuEnabled?: boolean;
|
||||
provisioned?: boolean;
|
||||
@ -81,5 +80,4 @@ export interface DashboardState {
|
||||
isInitSlow: boolean;
|
||||
initError: DashboardInitError | null;
|
||||
permissions: DashboardAcl[];
|
||||
modifiedQueries: QueriesToUpdateOnDashboardLoad | null;
|
||||
}
|
||||
|
@ -147,12 +147,6 @@ export interface ExploreItemState {
|
||||
|
||||
queryResponse: PanelData;
|
||||
|
||||
/**
|
||||
* Panel Id that is set if we come to explore from a penel. Used so we can get back to it and optionally modify the
|
||||
* query of that panel.
|
||||
*/
|
||||
originPanelId?: number | null;
|
||||
|
||||
showLogs?: boolean;
|
||||
showMetrics?: boolean;
|
||||
showTable?: boolean;
|
||||
|
Loading…
Reference in New Issue
Block a user