Remove return to panel button and related code (#45018)

This commit is contained in:
Kristina 2022-02-08 10:20:22 -06:00 committed by GitHub
parent 834d11691f
commit 4e38ac9cf7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 13 additions and 248 deletions

View File

@ -9,7 +9,6 @@ export interface ExploreUrlState<T extends DataQuery = AnyQuery> {
datasource: string;
queries: T[];
range: RawTimeRange;
originPanelId?: number;
context?: string;
panelsState?: ExplorePanelsState;
}

View File

@ -23,7 +23,6 @@ const DEFAULT_EXPLORE_STATE: ExploreUrlState = {
datasource: '',
queries: [],
range: DEFAULT_RANGE,
originPanelId: undefined,
};
describe('state functions', () => {

View File

@ -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 {

View File

@ -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;
});

View File

@ -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());
}

View File

@ -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;

View File

@ -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,
};
}

View File

@ -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

View File

@ -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);
});
});

View File

@ -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);

View File

@ -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,

View File

@ -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,
},
};
}

View File

@ -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;
}

View File

@ -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;