Commit 81859880 by Marcus Andersson Committed by GitHub

Annotations: fixing so when changing annotations query links submenu will be updated. (#28990)

* fixing so changes to annotations query links will update submenu.

* Refactored so we dont use the events to trigger a refresh but instead recreating the annotations list instead of mutating the existing list.

* updated snapshot.

* uppdates according to feedback.

* fixed so it also works to update a annotation.
parent 917b5c5f
...@@ -12,6 +12,7 @@ export interface AnnotationQuery<TQuery extends DataQuery = DataQuery> { ...@@ -12,6 +12,7 @@ export interface AnnotationQuery<TQuery extends DataQuery = DataQuery> {
enable: boolean; enable: boolean;
name: string; name: string;
iconColor: string; iconColor: string;
hide?: boolean;
// Standard datasource query // Standard datasource query
target?: TQuery; target?: TQuery;
......
...@@ -5,7 +5,7 @@ import coreModule from 'app/core/core_module'; ...@@ -5,7 +5,7 @@ import coreModule from 'app/core/core_module';
import { DashboardModel } from 'app/features/dashboard/state'; import { DashboardModel } from 'app/features/dashboard/state';
import DatasourceSrv from '../plugins/datasource_srv'; import DatasourceSrv from '../plugins/datasource_srv';
import appEvents from 'app/core/app_events'; import appEvents from 'app/core/app_events';
import { AppEvents } from '@grafana/data'; import { AnnotationQuery, AppEvents } from '@grafana/data';
// Registeres the angular directive // Registeres the angular directive
import './components/StandardAnnotationQueryEditor'; import './components/StandardAnnotationQueryEditor';
...@@ -13,7 +13,6 @@ import './components/StandardAnnotationQueryEditor'; ...@@ -13,7 +13,6 @@ import './components/StandardAnnotationQueryEditor';
export class AnnotationsEditorCtrl { export class AnnotationsEditorCtrl {
mode: any; mode: any;
datasources: any; datasources: any;
annotations: any[];
currentAnnotation: any; currentAnnotation: any;
currentDatasource: any; currentDatasource: any;
currentIsNew: any; currentIsNew: any;
...@@ -59,7 +58,7 @@ export class AnnotationsEditorCtrl { ...@@ -59,7 +58,7 @@ export class AnnotationsEditorCtrl {
this.dashboard = $scope.dashboard; this.dashboard = $scope.dashboard;
this.mode = 'list'; this.mode = 'list';
this.datasources = datasourceSrv.getAnnotationSources(); this.datasources = datasourceSrv.getAnnotationSources();
this.annotations = this.dashboard.annotations.list; this.dashboard.annotations.list = this.dashboard.annotations.list ?? [];
this.reset(); this.reset();
this.onColorChange = this.onColorChange.bind(this); this.onColorChange = this.onColorChange.bind(this);
...@@ -75,17 +74,25 @@ export class AnnotationsEditorCtrl { ...@@ -75,17 +74,25 @@ export class AnnotationsEditorCtrl {
/** /**
* Called from the react editor * Called from the react editor
*/ */
onAnnotationChange = (annotation: any) => { onAnnotationChange = (annotation: AnnotationQuery) => {
const currentIndex = this.dashboard.annotations.list.indexOf(this.currentAnnotation); let replaced = false;
if (currentIndex >= 0) {
this.dashboard.annotations.list[currentIndex] = annotation; this.dashboard.annotations.list = this.dashboard.annotations.list.map(a => {
} else { if (a.name !== annotation.name) {
return a;
}
replaced = true;
return annotation;
});
if (!replaced) {
console.warn('updating annotatoin, but not in the dashboard', annotation); console.warn('updating annotatoin, but not in the dashboard', annotation);
} }
this.currentAnnotation = annotation; this.currentAnnotation = annotation;
}; };
edit(annotation: any) { edit(annotation: AnnotationQuery) {
this.currentAnnotation = annotation; this.currentAnnotation = annotation;
this.currentAnnotation.showIn = this.currentAnnotation.showIn || 0; this.currentAnnotation.showIn = this.currentAnnotation.showIn || 0;
this.currentIsNew = false; this.currentIsNew = false;
...@@ -102,6 +109,7 @@ export class AnnotationsEditorCtrl { ...@@ -102,6 +109,7 @@ export class AnnotationsEditorCtrl {
} }
update() { update() {
this.dashboard.annotations.list = [...this.dashboard.annotations.list];
this.reset(); this.reset();
this.mode = 'list'; this.mode = 'list';
} }
...@@ -116,25 +124,27 @@ export class AnnotationsEditorCtrl { ...@@ -116,25 +124,27 @@ export class AnnotationsEditorCtrl {
} }
move(index: number, dir: number) { move(index: number, dir: number) {
// @ts-ignore const list = [...this.dashboard.annotations.list];
_.move(this.annotations, index, index + dir); Array.prototype.splice.call(list, index + dir, 0, Array.prototype.splice.call(list, index, 1)[0]);
this.dashboard.annotations.list = list;
} }
add() { add() {
const sameName: any = _.find(this.annotations, { name: this.currentAnnotation.name }); const sameName: any = _.find(this.dashboard.annotations.list, { name: this.currentAnnotation.name });
if (sameName) { if (sameName) {
appEvents.emit(AppEvents.alertWarning, ['Validation', 'Annotations with the same name already exists']); appEvents.emit(AppEvents.alertWarning, ['Validation', 'Annotations with the same name already exists']);
return; return;
} }
this.annotations.push(this.currentAnnotation); this.dashboard.annotations.list = [...this.dashboard.annotations.list, this.currentAnnotation];
this.reset(); this.reset();
this.mode = 'list'; this.mode = 'list';
this.dashboard.updateSubmenuVisibility(); this.dashboard.updateSubmenuVisibility();
} }
removeAnnotation(annotation: any) { removeAnnotation(annotation: AnnotationQuery) {
const index = _.indexOf(this.annotations, annotation); this.dashboard.annotations.list = this.dashboard.annotations.list.filter(a => {
this.annotations.splice(index, 1); return a.name !== annotation.name;
});
this.dashboard.updateSubmenuVisibility(); this.dashboard.updateSubmenuVisibility();
} }
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
type="button" type="button"
class="btn btn-primary" class="btn btn-primary"
ng-click="ctrl.setupNew();" ng-click="ctrl.setupNew();"
ng-if="ctrl.annotations.length > 1" ng-if="ctrl.dashboard.annotations.list.length > 1"
ng-hide="ctrl.mode === 'edit' || ctrl.mode === 'new'" ng-hide="ctrl.mode === 'edit' || ctrl.mode === 'new'"
> >
New New
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr ng-repeat="annotation in ctrl.annotations track by annotation.name"> <tr ng-repeat="annotation in ctrl.dashboard.annotations.list track by annotation.name">
<td style="width:90%" ng-hide="annotation.builtIn" class="pointer" ng-click="ctrl.edit(annotation)"> <td style="width:90%" ng-hide="annotation.builtIn" class="pointer" ng-click="ctrl.edit(annotation)">
<icon name="'comment-alt'" style="color:{{ annotation.iconColor }}"></icon> &nbsp; {{ annotation.name }} <icon name="'comment-alt'" style="color:{{ annotation.iconColor }}"></icon> &nbsp; {{ annotation.name }}
</td> </td>
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
</table> </table>
<!-- empty list cta, there is always one built in query --> <!-- empty list cta, there is always one built in query -->
<div ng-if="ctrl.annotations.length === 1" class="p-t-2"> <div ng-if="ctrl.dashboard.annotations.list.length === 1" class="p-t-2">
<empty-list-cta <empty-list-cta
title="ctrl.emptyListCta.title" title="ctrl.emptyListCta.title"
buttonIcon="ctrl.emptyListCta.buttonIcon" buttonIcon="ctrl.emptyListCta.buttonIcon"
......
import React, { FunctionComponent, useEffect, useState } from 'react'; import React, { FunctionComponent, useEffect, useState } from 'react';
import { LegacyForms } from '@grafana/ui'; import { LegacyForms } from '@grafana/ui';
import { AnnotationQuery } from '@grafana/data';
const { Switch } = LegacyForms; const { Switch } = LegacyForms;
interface Props { interface Props {
annotations: any[]; annotations: AnnotationQuery[];
onAnnotationChanged: (annotation: any) => void; onAnnotationChanged: (annotation: any) => void;
} }
......
...@@ -8,10 +8,12 @@ import { DashboardLinks } from './DashboardLinks'; ...@@ -8,10 +8,12 @@ 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'; import { DashboardLink } from '../../state/DashboardModel';
import { AnnotationQuery } from '@grafana/data';
interface OwnProps { interface OwnProps {
dashboard: DashboardModel; dashboard: DashboardModel;
links: DashboardLink[]; links: DashboardLink[];
annotations: AnnotationQuery[];
} }
interface ConnectedProps { interface ConnectedProps {
...@@ -51,7 +53,7 @@ class SubMenuUnConnected extends PureComponent<Props> { ...@@ -51,7 +53,7 @@ class SubMenuUnConnected extends PureComponent<Props> {
}; };
render() { render() {
const { dashboard, variables, links } = this.props; const { dashboard, variables, links, annotations } = this.props;
if (!this.isSubMenuVisible()) { if (!this.isSubMenuVisible()) {
return null; return null;
...@@ -60,7 +62,7 @@ class SubMenuUnConnected extends PureComponent<Props> { ...@@ -60,7 +62,7 @@ class SubMenuUnConnected extends PureComponent<Props> {
return ( return (
<div className="submenu-controls"> <div className="submenu-controls">
<SubMenuItems variables={variables} /> <SubMenuItems variables={variables} />
<Annotations annotations={dashboard.annotations.list} onAnnotationChanged={this.onAnnotationStateChanged} /> <Annotations annotations={annotations} onAnnotationChanged={this.onAnnotationStateChanged} />
<div className="gf-form gf-form--grow" /> <div className="gf-form gf-form--grow" />
{dashboard && <DashboardLinks dashboard={dashboard} links={links} />} {dashboard && <DashboardLinks dashboard={dashboard} links={links} />}
<div className="clearfix" /> <div className="clearfix" />
......
...@@ -320,7 +320,9 @@ export class DashboardPage extends PureComponent<Props, State> { ...@@ -320,7 +320,9 @@ 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} links={dashboard.links} />} {!editPanel && (
<SubMenu dashboard={dashboard} annotations={dashboard.annotations.list} links={dashboard.links} />
)}
<DashboardGrid <DashboardGrid
dashboard={dashboard} dashboard={dashboard}
......
...@@ -120,6 +120,19 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1` ...@@ -120,6 +120,19 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
className="dashboard-content" className="dashboard-content"
> >
<SubMenu <SubMenu
annotations={
Array [
Object {
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard",
},
]
}
dashboard={ dashboard={
DashboardModel { DashboardModel {
"annotations": Object { "annotations": Object {
...@@ -479,6 +492,19 @@ exports[`DashboardPage When dashboard has editview url state should render setti ...@@ -479,6 +492,19 @@ exports[`DashboardPage When dashboard has editview url state should render setti
className="dashboard-content" className="dashboard-content"
> >
<SubMenu <SubMenu
annotations={
Array [
Object {
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard",
},
]
}
dashboard={ dashboard={
DashboardModel { DashboardModel {
"annotations": Object { "annotations": Object {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment