DashboardLinks: do not over-query search endpoint (#26311)

* DashboardLinks: WIP fix for dashboard links issue

* Make the dashboard links update on change(hacky)

* Replace dashboard links with new array when updating/adding dash links

* Update snaps

* Deep clone dashboard links on save

Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>
This commit is contained in:
Torkel Ödegaard
2020-07-15 09:18:35 +02:00
committed by GitHub
parent 9c0536c2f7
commit 23e93175d1
7 changed files with 31 additions and 17 deletions

View File

@ -54,7 +54,7 @@ export class DashLinksEditorCtrl {
}; };
addLink() { addLink() {
this.dashboard.links.push(this.link); this.dashboard.links = [...this.dashboard.links, this.link];
this.mode = 'list'; this.mode = 'list';
this.dashboard.updateSubmenuVisibility(); this.dashboard.updateSubmenuVisibility();
} }
@ -65,6 +65,7 @@ export class DashLinksEditorCtrl {
} }
saveLink() { saveLink() {
this.dashboard.links = _.cloneDeep(this.dashboard.links);
this.backToList(); this.backToList();
} }

View File

@ -10,16 +10,17 @@ import { iconMap } from '../DashLinks/DashLinksEditorCtrl';
export interface Props { export interface Props {
dashboard: DashboardModel; dashboard: DashboardModel;
links: DashboardLink[];
} }
export const DashboardLinks: FC<Props> = ({ dashboard }) => { export const DashboardLinks: FC<Props> = ({ dashboard, links }) => {
if (!dashboard.links.length) { if (!links.length) {
return null; return null;
} }
return ( return (
<> <>
{dashboard.links.map((link: DashboardLink, index: number) => { {links.map((link: DashboardLink, index: number) => {
const linkInfo = getLinkSrv().getAnchorInfo(link); const linkInfo = getLinkSrv().getAnchorInfo(link);
const key = `${link.title}-$${index}`; const key = `${link.title}-$${index}`;

View File

@ -19,13 +19,17 @@ interface State {
export class DashboardLinksDashboard extends PureComponent<Props, State> { export class DashboardLinksDashboard extends PureComponent<Props, State> {
state: State = { resolvedLinks: [] }; state: State = { resolvedLinks: [] };
componentDidMount() {
this.searchForDashboards();
}
componentDidUpdate(prevProps: Readonly<Props>) { componentDidUpdate(prevProps: Readonly<Props>) {
if (!this.props.link.asDropdown && prevProps.linkInfo !== this.props.linkInfo) { if (this.props.link !== prevProps.link) {
this.onResolveLinks(); this.searchForDashboards();
} }
} }
onResolveLinks = async () => { searchForDashboards = async () => {
const { dashboardId, link } = this.props; const { dashboardId, link } = this.props;
const searchHits = await searchForTags(link); const searchHits = await searchForTags(link);
@ -73,7 +77,7 @@ export class DashboardLinksDashboard extends PureComponent<Props, State> {
<> <>
<a <a
className="gf-form-label pointer" className="gf-form-label pointer"
onClick={this.onResolveLinks} onClick={this.searchForDashboards}
data-placement="bottom" data-placement="bottom"
data-toggle="dropdown" data-toggle="dropdown"
> >

View File

@ -7,9 +7,11 @@ import { DashboardModel } from '../../state';
import { DashboardLinks } from './DashboardLinks'; import { DashboardLinks } from './DashboardLinks';
import { Annotations } from './Annotations'; import { Annotations } from './Annotations';
import { SubMenuItems } from './SubMenuItems'; import { SubMenuItems } from './SubMenuItems';
import { DashboardLink } from '../../state/DashboardModel';
interface OwnProps { interface OwnProps {
dashboard: DashboardModel; dashboard: DashboardModel;
links: DashboardLink[];
} }
interface ConnectedProps { interface ConnectedProps {
@ -49,7 +51,8 @@ class SubMenuUnConnected extends PureComponent<Props> {
}; };
render() { render() {
const { dashboard, variables } = this.props; const { dashboard, variables, links } = this.props;
if (!this.isSubMenuVisible()) { if (!this.isSubMenuVisible()) {
return null; return null;
} }
@ -59,16 +62,18 @@ class SubMenuUnConnected extends PureComponent<Props> {
<SubMenuItems variables={variables} /> <SubMenuItems variables={variables} />
<Annotations annotations={dashboard.annotations.list} onAnnotationChanged={this.onAnnotationStateChanged} /> <Annotations annotations={dashboard.annotations.list} onAnnotationChanged={this.onAnnotationStateChanged} />
<div className="gf-form gf-form--grow" /> <div className="gf-form gf-form--grow" />
{dashboard && <DashboardLinks dashboard={dashboard} />} {dashboard && <DashboardLinks dashboard={dashboard} links={links} />}
<div className="clearfix" /> <div className="clearfix" />
</div> </div>
); );
} }
} }
const mapStateToProps: MapStateToProps<ConnectedProps, OwnProps, StoreState> = state => ({ const mapStateToProps: MapStateToProps<ConnectedProps, OwnProps, StoreState> = state => {
variables: getSubMenuVariables(state), return {
}); variables: getSubMenuVariables(state.templating.variables),
};
};
export const SubMenu = connect(mapStateToProps)(SubMenuUnConnected); export const SubMenu = connect(mapStateToProps)(SubMenuUnConnected);
SubMenu.displayName = 'SubMenu'; SubMenu.displayName = 'SubMenu';

View File

@ -309,7 +309,7 @@ export class DashboardPage extends PureComponent<Props, State> {
> >
<div className="dashboard-content"> <div className="dashboard-content">
{initError && this.renderInitFailedState()} {initError && this.renderInitFailedState()}
{!editPanel && <SubMenu dashboard={dashboard} />} {!editPanel && <SubMenu dashboard={dashboard} links={dashboard.links} />}
<DashboardGrid <DashboardGrid
dashboard={dashboard} dashboard={dashboard}

View File

@ -211,6 +211,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
"version": 0, "version": 0,
} }
} }
links={Array []}
/> />
<DashboardGrid <DashboardGrid
dashboard={ dashboard={
@ -569,6 +570,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
"version": 0, "version": 0,
} }
} }
links={Array []}
/> />
<DashboardGrid <DashboardGrid
dashboard={ dashboard={

View File

@ -2,6 +2,7 @@ import { StoreState } from '../../../types';
import { VariableModel } from '../types'; import { VariableModel } from '../types';
import { getState } from '../../../store/store'; import { getState } from '../../../store/store';
import { NEW_VARIABLE_ID } from './types'; import { NEW_VARIABLE_ID } from './types';
import memoizeOne from 'memoize-one';
export const getVariable = <T extends VariableModel = VariableModel>( export const getVariable = <T extends VariableModel = VariableModel>(
id: string, id: string,
@ -42,9 +43,9 @@ export const getVariables = (state: StoreState = getState(), includeNewVariable
return getFilteredVariables(filter, state); return getFilteredVariables(filter, state);
}; };
export const getSubMenuVariables = (state: StoreState): VariableModel[] => { export const getSubMenuVariables = memoizeOne((variables: Record<string, VariableModel>): VariableModel[] => {
return getVariables(state); return getVariables(getState());
}; });
export const getEditorVariables = (state: StoreState): VariableModel[] => { export const getEditorVariables = (state: StoreState): VariableModel[] => {
return getVariables(state, true); return getVariables(state, true);