kibana/x-pack/plugins/monitoring/public/url_state.ts

170 lines
5.4 KiB
TypeScript
Raw Normal View History

/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { Subscription } from 'rxjs';
import { History, createHashHistory } from 'history';
[Monitoring] Out of the box alerting (#68805) * First draft, not quite working but a good start * More working * Support configuring throttle * Get the other alerts working too * More * Separate into individual files * Menu support as well as better integration in existing UIs * Red borders! * New overview style, and renamed alert * more visual updates * Update cpu usage and improve settings configuration in UI * Convert cluster health and license expiration alert to use legacy data model * Remove most of the custom UI and use the flyout * Add the actual alerts * Remove more code * Fix formatting * Fix up some errors * Remove unnecessary code * Updates * add more links here * Fix up linkage * Added nodes changed alert * Most of the version mismatch working * Add kibana mismatch * UI tweaks * Add timestamp * Support actions in the enable api * Move this around * Better support for changing legacy alerts * Add missing files * Update alerts * Enable alerts whenever any page is visited in SM * Tweaks * Use more practical default * Remove the buggy renderer and ensure setup mode can show all alerts * Updates * Remove unnecessary code * Remove some dead code * Cleanup * Fix snapshot * Fixes * Fixes * Fix test * Add alerts to kibana and logstash listing pages * Fix test * Add disable/mute options * Tweaks * Fix linting * Fix i18n * Adding a couple tests * Fix localization * Use http * Ensure we properly handle when an alert is resolved * Fix tests * Hide legacy alerts if not the right license * Design tweaks * Fix tests * PR feedback * Moar tests * Fix i18n * Ensure we have a control over the messaging * Fix translations * Tweaks * More localization * Copy changes * Type
2020-07-14 23:50:22 +02:00
import { MonitoringStartPluginDependencies } from './types';
import { Legacy } from './legacy_shims';
import {
RefreshInterval,
TimeRange,
syncQueryStateWithUrl,
} from '../../../../src/plugins/data/public';
import {
createStateContainer,
createKbnUrlStateStorage,
StateContainer,
INullableBaseStateContainer,
IKbnUrlStateStorage,
ISyncStateRef,
syncState,
} from '../../../../src/plugins/kibana_utils/public';
interface Route {
params: { _g: unknown };
}
interface RawObject {
[key: string]: unknown;
}
export interface MonitoringAppState {
[key: string]: unknown;
cluster_uuid?: string;
ccs?: boolean;
inSetupMode?: boolean;
refreshInterval?: RefreshInterval;
time?: TimeRange;
filters?: any[];
}
export interface MonitoringAppStateTransitions {
set: (
state: MonitoringAppState
) => <T extends keyof MonitoringAppState>(
prop: T,
value: MonitoringAppState[T]
) => MonitoringAppState;
}
const GLOBAL_STATE_KEY = '_g';
const objectEquals = (objA: any, objB: any) => JSON.stringify(objA) === JSON.stringify(objB);
export class GlobalState {
private readonly stateSyncRef: ISyncStateRef;
private readonly stateContainer: StateContainer<
MonitoringAppState,
MonitoringAppStateTransitions
>;
private readonly stateStorage: IKbnUrlStateStorage;
private readonly stateContainerChangeSub: Subscription;
private readonly syncQueryStateWithUrlManager: { stop: () => void };
[Monitoring] Out of the box alerting (#68805) * First draft, not quite working but a good start * More working * Support configuring throttle * Get the other alerts working too * More * Separate into individual files * Menu support as well as better integration in existing UIs * Red borders! * New overview style, and renamed alert * more visual updates * Update cpu usage and improve settings configuration in UI * Convert cluster health and license expiration alert to use legacy data model * Remove most of the custom UI and use the flyout * Add the actual alerts * Remove more code * Fix formatting * Fix up some errors * Remove unnecessary code * Updates * add more links here * Fix up linkage * Added nodes changed alert * Most of the version mismatch working * Add kibana mismatch * UI tweaks * Add timestamp * Support actions in the enable api * Move this around * Better support for changing legacy alerts * Add missing files * Update alerts * Enable alerts whenever any page is visited in SM * Tweaks * Use more practical default * Remove the buggy renderer and ensure setup mode can show all alerts * Updates * Remove unnecessary code * Remove some dead code * Cleanup * Fix snapshot * Fixes * Fixes * Fix test * Add alerts to kibana and logstash listing pages * Fix test * Add disable/mute options * Tweaks * Fix linting * Fix i18n * Adding a couple tests * Fix localization * Use http * Ensure we properly handle when an alert is resolved * Fix tests * Hide legacy alerts if not the right license * Design tweaks * Fix tests * PR feedback * Moar tests * Fix i18n * Ensure we have a control over the messaging * Fix translations * Tweaks * More localization * Copy changes * Type
2020-07-14 23:50:22 +02:00
private readonly timefilterRef: MonitoringStartPluginDependencies['data']['query']['timefilter']['timefilter'];
private lastAssignedState: MonitoringAppState = {};
private lastKnownGlobalState?: string;
constructor(
[Monitoring] Out of the box alerting (#68805) * First draft, not quite working but a good start * More working * Support configuring throttle * Get the other alerts working too * More * Separate into individual files * Menu support as well as better integration in existing UIs * Red borders! * New overview style, and renamed alert * more visual updates * Update cpu usage and improve settings configuration in UI * Convert cluster health and license expiration alert to use legacy data model * Remove most of the custom UI and use the flyout * Add the actual alerts * Remove more code * Fix formatting * Fix up some errors * Remove unnecessary code * Updates * add more links here * Fix up linkage * Added nodes changed alert * Most of the version mismatch working * Add kibana mismatch * UI tweaks * Add timestamp * Support actions in the enable api * Move this around * Better support for changing legacy alerts * Add missing files * Update alerts * Enable alerts whenever any page is visited in SM * Tweaks * Use more practical default * Remove the buggy renderer and ensure setup mode can show all alerts * Updates * Remove unnecessary code * Remove some dead code * Cleanup * Fix snapshot * Fixes * Fixes * Fix test * Add alerts to kibana and logstash listing pages * Fix test * Add disable/mute options * Tweaks * Fix linting * Fix i18n * Adding a couple tests * Fix localization * Use http * Ensure we properly handle when an alert is resolved * Fix tests * Hide legacy alerts if not the right license * Design tweaks * Fix tests * PR feedback * Moar tests * Fix i18n * Ensure we have a control over the messaging * Fix translations * Tweaks * More localization * Copy changes * Type
2020-07-14 23:50:22 +02:00
queryService: MonitoringStartPluginDependencies['data']['query'],
rootScope: ng.IRootScopeService,
ngLocation: ng.ILocationService,
externalState: RawObject
) {
this.timefilterRef = queryService.timefilter.timefilter;
const history: History = createHashHistory();
this.stateStorage = createKbnUrlStateStorage({ useHash: false, history });
const initialStateFromUrl = this.stateStorage.get(GLOBAL_STATE_KEY) as MonitoringAppState;
this.stateContainer = createStateContainer(initialStateFromUrl, {
2020-05-22 09:08:58 +02:00
set: (state) => (prop, value) => ({ ...state, [prop]: value }),
});
this.stateSyncRef = syncState({
storageKey: GLOBAL_STATE_KEY,
stateContainer: this.stateContainer as INullableBaseStateContainer<MonitoringAppState>,
stateStorage: this.stateStorage,
});
this.stateContainerChangeSub = this.stateContainer.state$.subscribe(() => {
this.lastAssignedState = this.getState();
if (!this.stateContainer.get() && this.lastKnownGlobalState) {
ngLocation.search(`${GLOBAL_STATE_KEY}=${this.lastKnownGlobalState}`).replace();
}
Legacy.shims.breadcrumbs.update();
this.syncExternalState(externalState);
rootScope.$applyAsync();
});
this.syncQueryStateWithUrlManager = syncQueryStateWithUrl(queryService, this.stateStorage);
this.stateSyncRef.start();
this.startHashSync(rootScope, ngLocation);
this.lastAssignedState = this.getState();
rootScope.$on('$destroy', () => this.destroy());
}
private syncExternalState(externalState: { [key: string]: unknown }) {
const currentState = this.stateContainer.get();
for (const key in currentState) {
if (
({ save: 1, time: 1, refreshInterval: 1, filters: 1 } as { [key: string]: number })[key]
) {
continue;
}
if (currentState[key] !== externalState[key]) {
externalState[key] = currentState[key];
}
}
}
private startHashSync(rootScope: ng.IRootScopeService, ngLocation: ng.ILocationService) {
rootScope.$on(
'$routeChangeStart',
(_: { preventDefault: () => void }, newState: Route, oldState: Route) => {
const currentGlobalState = oldState?.params?._g;
const nextGlobalState = newState?.params?._g;
if (!nextGlobalState && currentGlobalState && typeof currentGlobalState === 'string') {
newState.params._g = currentGlobalState;
ngLocation.search(`${GLOBAL_STATE_KEY}=${currentGlobalState}`).replace();
}
this.lastKnownGlobalState = (nextGlobalState || currentGlobalState) as string;
}
);
}
public setState(state?: { [key: string]: unknown }) {
const currentAppState = this.getState();
const newAppState = { ...currentAppState, ...state };
if (state && objectEquals(newAppState, currentAppState)) {
return;
}
const newState = {
...newAppState,
refreshInterval: this.timefilterRef.getRefreshInterval(),
time: this.timefilterRef.getTime(),
};
this.lastAssignedState = newState;
this.stateContainer.set(newState);
}
public getState(): MonitoringAppState {
const currentState = { ...this.lastAssignedState, ...this.stateContainer.get() };
delete currentState.filters;
const { refreshInterval: _nullA, time: _nullB, ...currentAppState } = currentState;
return currentAppState || {};
}
public destroy() {
this.syncQueryStateWithUrlManager.stop();
this.stateContainerChangeSub.unsubscribe();
this.stateSyncRef.stop();
}
}