mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
173 lines
4.6 KiB
TypeScript
173 lines
4.6 KiB
TypeScript
import { getGrafanaLiveSrv, getLegacyAngularInjector } from '@grafana/runtime';
|
|
import { getDashboardSrv } from '../../dashboard/services/DashboardSrv';
|
|
import { appEvents } from 'app/core/core';
|
|
import {
|
|
AppEvents,
|
|
LiveChannel,
|
|
LiveChannelScope,
|
|
LiveChannelEvent,
|
|
LiveChannelConfig,
|
|
LiveChannelConnectionState,
|
|
isLiveChannelStatusEvent,
|
|
isLiveChannelMessageEvent,
|
|
} from '@grafana/data';
|
|
import { CoreEvents } from 'app/types';
|
|
import { DashboardChangedModal } from './DashboardChangedModal';
|
|
import { DashboardEvent, DashboardEventAction } from './types';
|
|
import { CoreGrafanaLiveFeature } from '../scopes';
|
|
import { sessionId } from '../live';
|
|
|
|
class DashboardWatcher {
|
|
channel?: LiveChannel<DashboardEvent>;
|
|
|
|
uid?: string;
|
|
ignoreSave?: boolean;
|
|
editing = false;
|
|
|
|
setEditingState(state: boolean) {
|
|
const changed = (this.editing = state);
|
|
this.editing = state;
|
|
|
|
if (changed) {
|
|
this.sendEditingState();
|
|
}
|
|
}
|
|
|
|
private sendEditingState() {
|
|
if (!this.channel?.publish) {
|
|
return;
|
|
}
|
|
|
|
const msg: DashboardEvent = {
|
|
sessionId,
|
|
uid: this.uid!,
|
|
action: this.editing ? DashboardEventAction.EditingStarted : DashboardEventAction.EditingCanceled,
|
|
message: 'user (name)',
|
|
};
|
|
this.channel!.publish!(msg);
|
|
}
|
|
|
|
watch(uid: string) {
|
|
const live = getGrafanaLiveSrv();
|
|
if (!live) {
|
|
return;
|
|
}
|
|
|
|
// Check for changes
|
|
if (uid !== this.uid) {
|
|
this.leave();
|
|
this.channel = live.getChannel({
|
|
scope: LiveChannelScope.Grafana,
|
|
namespace: 'dashboard',
|
|
path: uid,
|
|
});
|
|
this.channel.getStream().subscribe(this.observer);
|
|
this.uid = uid;
|
|
}
|
|
|
|
console.log('Watch', uid);
|
|
}
|
|
|
|
leave() {
|
|
if (this.channel) {
|
|
this.channel.disconnect();
|
|
}
|
|
this.uid = undefined;
|
|
}
|
|
|
|
ignoreNextSave() {
|
|
this.ignoreSave = true;
|
|
}
|
|
|
|
observer = {
|
|
next: (event: LiveChannelEvent<DashboardEvent>) => {
|
|
// Send the editing state when connection starts
|
|
if (isLiveChannelStatusEvent(event) && this.editing && event.state === LiveChannelConnectionState.Connected) {
|
|
this.sendEditingState();
|
|
}
|
|
|
|
if (isLiveChannelMessageEvent(event)) {
|
|
if (event.message.sessionId === sessionId) {
|
|
return; // skip internal messages
|
|
}
|
|
|
|
const { action } = event.message;
|
|
switch (action) {
|
|
case DashboardEventAction.EditingStarted:
|
|
case DashboardEventAction.Saved: {
|
|
if (this.ignoreSave) {
|
|
this.ignoreSave = false;
|
|
return;
|
|
}
|
|
|
|
const dash = getDashboardSrv().getCurrent();
|
|
if (dash.uid !== event.message.uid) {
|
|
console.log('dashboard event for different dashboard?', event, dash);
|
|
return;
|
|
}
|
|
|
|
const changeTracker = getLegacyAngularInjector().get<any>('unsavedChangesSrv').tracker;
|
|
const showPopup = this.editing || changeTracker.hasChanges();
|
|
|
|
if (action === DashboardEventAction.Saved) {
|
|
if (showPopup) {
|
|
appEvents.emit(CoreEvents.showModalReact, {
|
|
component: DashboardChangedModal,
|
|
props: { event },
|
|
});
|
|
} else {
|
|
appEvents.emit(AppEvents.alertSuccess, ['Dashboard updated']);
|
|
this.reloadPage();
|
|
}
|
|
} else if (showPopup) {
|
|
if (action === DashboardEventAction.EditingStarted) {
|
|
appEvents.emit(AppEvents.alertWarning, [
|
|
'Another session is editing this dashboard',
|
|
event.message.message,
|
|
]);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
console.log('DashboardEvent EVENT', event);
|
|
},
|
|
};
|
|
|
|
reloadPage() {
|
|
const $route = getLegacyAngularInjector().get<any>('$route');
|
|
if ($route) {
|
|
$route.reload();
|
|
} else {
|
|
location.reload();
|
|
}
|
|
}
|
|
}
|
|
|
|
export const dashboardWatcher = new DashboardWatcher();
|
|
|
|
export function getDashboardChannelsFeature(): CoreGrafanaLiveFeature {
|
|
const dashboardConfig: LiveChannelConfig = {
|
|
path: '${uid}',
|
|
description: 'Dashboard change events',
|
|
variables: [{ value: 'uid', label: '${uid}', description: 'unique id for a dashboard' }],
|
|
hasPresence: true,
|
|
canPublish: () => true,
|
|
};
|
|
|
|
return {
|
|
name: 'dashboard',
|
|
support: {
|
|
getChannelConfig: (path: string) => {
|
|
return {
|
|
...dashboardConfig,
|
|
path, // set the real path
|
|
};
|
|
},
|
|
getSupportedPaths: () => [dashboardConfig],
|
|
},
|
|
description: 'Dashboard listener',
|
|
};
|
|
}
|