Compare commits

...

3 Commits

Author SHA1 Message Date
Tom Ratcliffe
a0f73a275d Remove history event 2025-11-13 16:54:34 +00:00
Tom Ratcliffe
e13c62433c Remove translations 2025-11-13 16:54:25 +00:00
Tom Ratcliffe
01b7034eaf --wip-- 2025-11-13 16:42:34 +00:00
13 changed files with 1 additions and 544 deletions

View File

@@ -801,10 +801,6 @@ export interface FeatureToggles {
*/ */
elasticsearchCrossClusterSearch?: boolean; elasticsearchCrossClusterSearch?: boolean;
/** /**
* Displays the navigation history so the user can navigate back to previous pages
*/
unifiedHistory?: boolean;
/**
* Defaults to using the Loki `/labels` API instead of `/series` * Defaults to using the Loki `/labels` API instead of `/series`
* @default true * @default true
*/ */

View File

@@ -1383,13 +1383,6 @@ var (
Owner: grafanaPartnerPluginsSquad, Owner: grafanaPartnerPluginsSquad,
Expression: "false", Expression: "false",
}, },
{
Name: "unifiedHistory",
Description: "Displays the navigation history so the user can navigate back to previous pages",
Stage: FeatureStageExperimental,
Owner: grafanaFrontendSearchNavOrganise,
FrontendOnly: true,
},
{ {
// Remove this flag once Loki v4 is released and the min supported version is v3.0+, // Remove this flag once Loki v4 is released and the min supported version is v3.0+,
// since users on v2.9 need it to disable the feature, as it doesn't work for them. // since users on v2.9 need it to disable the feature, as it doesn't work for them.

View File

@@ -180,7 +180,6 @@ alertingNotificationsStepMode,GA,@grafana/alerting-squad,false,false,true
feedbackButton,experimental,@grafana/grafana-operator-experience-squad,false,false,false feedbackButton,experimental,@grafana/grafana-operator-experience-squad,false,false,false
unifiedStorageSearchUI,experimental,@grafana/search-and-storage,false,false,false unifiedStorageSearchUI,experimental,@grafana/search-and-storage,false,false,false
elasticsearchCrossClusterSearch,GA,@grafana/partner-datasources,false,false,false elasticsearchCrossClusterSearch,GA,@grafana/partner-datasources,false,false,false
unifiedHistory,experimental,@grafana/grafana-search-navigate-organise,false,false,true
lokiLabelNamesQueryApi,GA,@grafana/observability-logs,false,false,false lokiLabelNamesQueryApi,GA,@grafana/observability-logs,false,false,false
investigationsBackend,experimental,@grafana/grafana-app-platform-squad,false,false,false investigationsBackend,experimental,@grafana/grafana-app-platform-squad,false,false,false
k8SFolderCounts,experimental,@grafana/search-and-storage,false,false,false k8SFolderCounts,experimental,@grafana/search-and-storage,false,false,false
1 Name Stage Owner requiresDevMode RequiresRestart FrontendOnly
180 feedbackButton experimental @grafana/grafana-operator-experience-squad false false false
181 unifiedStorageSearchUI experimental @grafana/search-and-storage false false false
182 elasticsearchCrossClusterSearch GA @grafana/partner-datasources false false false
unifiedHistory experimental @grafana/grafana-search-navigate-organise false false true
183 lokiLabelNamesQueryApi GA @grafana/observability-logs false false false
184 investigationsBackend experimental @grafana/grafana-app-platform-squad false false false
185 k8SFolderCounts experimental @grafana/search-and-storage false false false

View File

@@ -731,10 +731,6 @@ const (
// Enables cross cluster search in the Elasticsearch data source // Enables cross cluster search in the Elasticsearch data source
FlagElasticsearchCrossClusterSearch = "elasticsearchCrossClusterSearch" FlagElasticsearchCrossClusterSearch = "elasticsearchCrossClusterSearch"
// FlagUnifiedHistory
// Displays the navigation history so the user can navigate back to previous pages
FlagUnifiedHistory = "unifiedHistory"
// FlagLokiLabelNamesQueryApi // FlagLokiLabelNamesQueryApi
// Defaults to using the Loki `/labels` API instead of `/series` // Defaults to using the Loki `/labels` API instead of `/series`
FlagLokiLabelNamesQueryApi = "lokiLabelNamesQueryApi" FlagLokiLabelNamesQueryApi = "lokiLabelNamesQueryApi"

View File

@@ -4136,6 +4136,7 @@
"name": "unifiedHistory", "name": "unifiedHistory",
"resourceVersion": "1762958248290", "resourceVersion": "1762958248290",
"creationTimestamp": "2024-12-13T10:41:18Z", "creationTimestamp": "2024-12-13T10:41:18Z",
"deletionTimestamp": "2025-11-13T16:25:53Z",
"annotations": { "annotations": {
"grafana.app/updatedTimestamp": "2025-11-12 14:37:28.29086 +0000 UTC" "grafana.app/updatedTimestamp": "2025-11-12 14:37:28.29086 +0000 UTC"
} }

View File

@@ -10,11 +10,8 @@ import { isShallowEqual } from 'app/core/utils/isShallowEqual';
import { KioskMode } from 'app/types/dashboard'; import { KioskMode } from 'app/types/dashboard';
import { RouteDescriptor } from '../../navigation/types'; import { RouteDescriptor } from '../../navigation/types';
import { buildBreadcrumbs } from '../Breadcrumbs/utils';
import { logDuplicateUnifiedHistoryEntryEvent } from './History/eventsTracking';
import { ReturnToPreviousProps } from './ReturnToPrevious/ReturnToPrevious'; import { ReturnToPreviousProps } from './ReturnToPrevious/ReturnToPrevious';
import { HistoryEntry } from './types';
export interface AppChromeState { export interface AppChromeState {
chromeless?: boolean; chromeless?: boolean;
@@ -34,7 +31,6 @@ export interface AppChromeState {
export const DOCKED_LOCAL_STORAGE_KEY = 'grafana.navigation.docked'; export const DOCKED_LOCAL_STORAGE_KEY = 'grafana.navigation.docked';
export const DOCKED_MENU_OPEN_LOCAL_STORAGE_KEY = 'grafana.navigation.open'; export const DOCKED_MENU_OPEN_LOCAL_STORAGE_KEY = 'grafana.navigation.open';
export const HISTORY_LOCAL_STORAGE_KEY = 'grafana.navigation.history';
export class AppChromeService { export class AppChromeService {
searchBarStorageKey = 'SearchBar_Hidden'; searchBarStorageKey = 'SearchBar_Hidden';
@@ -88,8 +84,6 @@ export class AppChromeService {
newState.chromeless = newState.kioskMode === KioskMode.Full || this.currentRoute?.chromeless; newState.chromeless = newState.kioskMode === KioskMode.Full || this.currentRoute?.chromeless;
if (!this.ignoreStateUpdate(newState, current)) { if (!this.ignoreStateUpdate(newState, current)) {
config.featureToggles.unifiedHistory &&
store.setObject(HISTORY_LOCAL_STORAGE_KEY, this.getUpdatedHistory(newState));
this.state.next(newState); this.state.next(newState);
} }
} }
@@ -118,40 +112,6 @@ export class AppChromeService {
window.sessionStorage.removeItem('returnToPrevious'); window.sessionStorage.removeItem('returnToPrevious');
}; };
private getUpdatedHistory(newState: AppChromeState): HistoryEntry[] {
const breadcrumbs = buildBreadcrumbs(newState.sectionNav.node, newState.pageNav, { text: 'Home', url: '/' }, true);
const newPageNav = newState.pageNav || newState.sectionNav.node;
let entries = store.getObject<HistoryEntry[]>(HISTORY_LOCAL_STORAGE_KEY, []);
const clickedHistory = store.getObject<boolean>('CLICKING_HISTORY');
if (clickedHistory) {
store.setObject('CLICKING_HISTORY', false);
return entries;
}
if (!newPageNav) {
return entries;
}
const lastEntry = entries[0];
const newEntry = { name: newPageNav.text, views: [], breadcrumbs, time: Date.now(), url: window.location.href };
const isSamePath = lastEntry && newEntry.url.split('?')[0] === lastEntry.url.split('?')[0];
// To avoid adding an entry with the same path twice, we always use the latest one
if (isSamePath) {
entries[0] = newEntry;
} else {
if (lastEntry && lastEntry.name === newEntry.name) {
logDuplicateUnifiedHistoryEntryEvent({
entryName: newEntry.name,
lastEntryURL: lastEntry.url,
newEntryURL: newEntry.url,
});
}
entries = [newEntry, ...entries];
}
return entries;
}
private ignoreStateUpdate(newState: AppChromeState, current: AppChromeState) { private ignoreStateUpdate(newState: AppChromeState, current: AppChromeState) {
if (isShallowEqual(newState, current)) { if (isShallowEqual(newState, current)) {
return true; return true;

View File

@@ -1,87 +0,0 @@
import { css } from '@emotion/css';
import { useEffect } from 'react';
import { useToggle } from 'react-use';
import { GrafanaTheme2, store } from '@grafana/data';
import { t } from '@grafana/i18n';
import { Drawer, ToolbarButton, useStyles2 } from '@grafana/ui';
import { appEvents } from 'app/core/app_events';
import { RecordHistoryEntryEvent } from 'app/types/events';
import { HISTORY_LOCAL_STORAGE_KEY } from '../AppChromeService';
import { NavToolbarSeparator } from '../NavToolbar/NavToolbarSeparator';
import { HistoryEntry } from '../types';
import { HistoryWrapper } from './HistoryWrapper';
import { logUnifiedHistoryDrawerInteractionEvent } from './eventsTracking';
export function HistoryContainer() {
const [showHistoryDrawer, onToggleShowHistoryDrawer] = useToggle(false);
const styles = useStyles2(getStyles);
useEffect(() => {
const sub = appEvents.subscribe(RecordHistoryEntryEvent, (ev) => {
const clickedHistory = store.getObject<boolean>('CLICKING_HISTORY');
if (clickedHistory) {
store.setObject('CLICKING_HISTORY', false);
return;
}
const history = store.getObject<HistoryEntry[]>(HISTORY_LOCAL_STORAGE_KEY, []);
let lastEntry = history[0];
const newUrl = ev.payload.url;
const lastUrl = lastEntry.views[0]?.url;
if (lastUrl !== newUrl) {
lastEntry.views = [
{
name: ev.payload.name,
description: ev.payload.description,
url: newUrl,
time: Date.now(),
},
...lastEntry.views,
];
store.setObject(HISTORY_LOCAL_STORAGE_KEY, [...history]);
}
return () => {
sub.unsubscribe();
};
});
}, []);
return (
<>
<ToolbarButton
onClick={() => {
onToggleShowHistoryDrawer();
logUnifiedHistoryDrawerInteractionEvent({ type: 'open' });
}}
iconOnly
icon="history"
aria-label={t('nav.history-container.drawer-tittle', 'History')}
/>
<NavToolbarSeparator className={styles.separator} />
{showHistoryDrawer && (
<Drawer
title={t('nav.history-container.drawer-tittle', 'History')}
onClose={() => {
onToggleShowHistoryDrawer();
logUnifiedHistoryDrawerInteractionEvent({ type: 'close' });
}}
size="sm"
>
<HistoryWrapper onClose={() => onToggleShowHistoryDrawer(false)} />
</Drawer>
)}
</>
);
}
const getStyles = (theme: GrafanaTheme2) => {
return {
separator: css({
[theme.breakpoints.down('sm')]: {
display: 'none',
},
}),
};
};

View File

@@ -1,291 +0,0 @@
import { css, cx } from '@emotion/css';
import moment from 'moment';
import { useState } from 'react';
import { FieldType, GrafanaTheme2, store } from '@grafana/data';
import { t } from '@grafana/i18n';
import { Box, Button, Card, Icon, IconButton, Space, Sparkline, Stack, Text, useStyles2, useTheme2 } from '@grafana/ui';
import { formatDate } from 'app/core/internationalization/dates';
import { HISTORY_LOCAL_STORAGE_KEY } from '../AppChromeService';
import { HistoryEntry } from '../types';
import { logClickUnifiedHistoryEntryEvent, logUnifiedHistoryShowMoreEvent } from './eventsTracking';
export function HistoryWrapper({ onClose }: { onClose: () => void }) {
const history = store.getObject<HistoryEntry[]>(HISTORY_LOCAL_STORAGE_KEY, []).filter((entry) => {
return moment(entry.time).isAfter(moment().subtract(2, 'day').startOf('day'));
});
const [numItemsToShow, setNumItemsToShow] = useState(5);
const selectedTime = history.find((entry) => {
return entry.url === window.location.href || entry.views.some((view) => view.url === window.location.href);
})?.time;
const hist = history.slice(0, numItemsToShow).reduce((acc: { [key: string]: HistoryEntry[] }, entry) => {
const date = moment(entry.time);
let key = '';
if (date.isSame(moment(), 'day')) {
key = t('nav.history-wrapper.today', 'Today');
} else if (date.isSame(moment().subtract(1, 'day'), 'day')) {
key = t('nav.history-wrapper.yesterday', 'Yesterday');
} else {
key = date.format('YYYY-MM-DD');
}
acc[key] = [...(acc[key] || []), entry];
return acc;
}, {});
const styles = useStyles2(getStyles);
return (
<Stack direction="column" alignItems="flex-start">
<Box width="100%">
{Object.keys(hist).map((entries, date) => {
return (
<Stack key={date} direction="column" gap={1}>
<Box paddingLeft={2}>
<Text color="secondary">{entries}</Text>
</Box>
<div className={styles.timeline}>
{hist[entries].map((entry, index) => {
return (
<HistoryEntryAppView
key={index}
entry={entry}
isSelected={entry.time === selectedTime}
onClick={() => onClose()}
/>
);
})}
</div>
</Stack>
);
})}
</Box>
{history.length > numItemsToShow && (
<Box paddingLeft={2}>
<Button
variant="secondary"
fill="text"
onClick={() => {
setNumItemsToShow(numItemsToShow + 5);
logUnifiedHistoryShowMoreEvent();
}}
>
{t('nav.history-wrapper.show-more', 'Show more')}
</Button>
</Box>
)}
</Stack>
);
}
interface ItemProps {
entry: HistoryEntry;
isSelected: boolean;
onClick: () => void;
}
function HistoryEntryAppView({ entry, isSelected, onClick }: ItemProps) {
const styles = useStyles2(getStyles);
const theme = useTheme2();
const [isExpanded, setIsExpanded] = useState(isSelected && entry.views.length > 0);
const { breadcrumbs, views, time, url, sparklineData } = entry;
const expandedLabel = isExpanded
? t('nav.history-wrapper.collapse', 'Collapse')
: t('nav.history-wrapper.expand', 'Expand');
const entryIconLabel = isExpanded
? t('nav.history-wrapper.icon-selected', 'Selected Entry')
: t('nav.history-wrapper.icon-unselected', 'Normal Entry');
const selectedViewTime =
isSelected &&
entry.views.find((entry) => {
return entry.url === window.location.href;
})?.time;
return (
<Box marginBottom={1}>
<Stack direction="column" gap={1}>
<Stack alignItems="baseline">
{views.length > 0 ? (
<IconButton
name={isExpanded ? 'angle-down' : 'angle-right'}
onClick={() => setIsExpanded(!isExpanded)}
aria-label={expandedLabel}
className={styles.iconButton}
/>
) : (
<Space h={2} />
)}
<Icon
size="sm"
name={isSelected ? 'circle-mono' : 'circle'}
aria-label={entryIconLabel}
className={isExpanded ? styles.iconButtonDot : styles.iconButtonCircle}
/>
<Card
noMargin
onClick={() => {
store.setObject('CLICKING_HISTORY', true);
onClick();
logClickUnifiedHistoryEntryEvent({ entryURL: url });
}}
href={url}
isCompact={true}
className={isSelected ? styles.card : cx(styles.card, styles.cardSelected)}
>
<Stack direction="column">
<div>
{breadcrumbs.map((breadcrumb, index) => (
<Text key={index}>
{breadcrumb.text}{' '}
{index !== breadcrumbs.length - 1
? // eslint-disable-next-line @grafana/i18n/no-untranslated-strings
'> '
: ''}
</Text>
))}
</div>
<Text variant="bodySmall" color="secondary">
{formatDate(time, { timeStyle: 'short' })}
</Text>
{sparklineData && (
<Sparkline
theme={theme}
width={240}
height={40}
config={{
custom: {
fillColor: 'rgba(130, 181, 216, 0.1)',
lineColor: '#82B5D8',
},
}}
sparkline={{
y: {
type: FieldType.number,
name: 'test',
config: {},
values: sparklineData.values,
state: {
range: {
...sparklineData.range,
},
},
},
}}
/>
)}
</Stack>
</Card>
</Stack>
{isExpanded && (
<div className={styles.expanded}>
{views.map((view, index) => {
return (
<Card
key={index}
noMargin
href={view.url}
onClick={() => {
store.setObject('CLICKING_HISTORY', true);
onClick();
logClickUnifiedHistoryEntryEvent({ entryURL: view.url, subEntry: 'timeRange' });
}}
isCompact={true}
className={view.time === selectedViewTime ? undefined : styles.subCard}
>
<Stack direction="column" gap={0}>
<Text variant="bodySmall">{view.name}</Text>
{view.description && (
<Text color="secondary" variant="bodySmall">
{view.description}
</Text>
)}
</Stack>
</Card>
);
})}
</div>
)}
</Stack>
</Box>
);
}
const getStyles = (theme: GrafanaTheme2) => {
return {
card: css({
label: 'card',
background: 'none',
margin: theme.spacing(0.5, 0),
}),
cardSelected: css({
label: 'card-selected',
background: 'none',
}),
subCard: css({
label: 'subcard',
background: 'none',
margin: 0,
}),
iconButton: css({
label: 'expand-button',
margin: 0,
}),
iconButtonCircle: css({
label: 'blue-circle-icon',
margin: 0,
background: theme.colors.background.primary,
fill: theme.colors.primary.main,
cursor: 'default',
'&:hover:before': {
background: 'none',
},
//Need this to place the icon on the line, otherwise the line will appear on top of the icon
zIndex: 0,
}),
iconButtonDot: css({
label: 'blue-dot-icon',
margin: 0,
color: theme.colors.primary.main,
border: theme.shape.radius.circle,
cursor: 'default',
'&:hover:before': {
background: 'none',
},
//Need this to place the icon on the line, otherwise the line will appear on top of the icon
zIndex: 0,
}),
expanded: css({
label: 'expanded',
display: 'flex',
flexDirection: 'column',
marginLeft: theme.spacing(6),
gap: theme.spacing(1),
position: 'relative',
'&:before': {
content: '""',
position: 'absolute',
left: 0,
top: 0,
height: '100%',
width: '1px',
background: theme.colors.border.weak,
},
}),
timeline: css({
label: 'timeline',
position: 'relative',
height: '100%',
width: '100%',
paddingLeft: theme.spacing(2),
'&:before': {
content: '""',
position: 'absolute',
left: theme.spacing(5.75),
top: 0,
height: '100%',
width: '1px',
borderLeft: `1px dashed ${theme.colors.border.strong}`,
},
}),
};
};

View File

@@ -1,64 +0,0 @@
import { reportInteraction } from '@grafana/runtime';
const UNIFIED_HISTORY_ENTRY_CLICKED = 'grafana_unified_history_entry_clicked';
const UNIFIED_HISTORY_ENTRY_DUPLICATED = 'grafana_unified_history_duplicated_entry_rendered';
const UNIFIED_HISTORY_DRAWER_INTERACTION = 'grafana_unified_history_drawer_interaction';
const UNIFIED_HISTORY_DRAWER_SHOW_MORE = 'grafana_unified_history_show_more';
//Currently just 'timeRange' is supported
//in short term, we could add 'templateVariables' for example
type subEntryTypes = 'timeRange';
//Whether the user opens or closes the `HistoryDrawer`
type UnifiedHistoryDrawerInteraction = 'open' | 'close';
interface UnifiedHistoryEntryClicked {
//We will also work with the current URL but we will get this from Rudderstack data
//URL to return to
entryURL: string;
//In the case we want to go back to a specific query param, currently just a specific time range
subEntry?: subEntryTypes;
}
interface UnifiedHistoryEntryDuplicated {
// Common name of the history entries
entryName: string;
// URL of the last entry
lastEntryURL: string;
// URL of the new entry
newEntryURL: string;
}
//Event triggered when a user clicks on an entry of the `HistoryDrawer`
export const logClickUnifiedHistoryEntryEvent = ({ entryURL, subEntry }: UnifiedHistoryEntryClicked) => {
reportInteraction(UNIFIED_HISTORY_ENTRY_CLICKED, {
entryURL,
subEntry,
});
};
//Event triggered when history entry name matches the previous one
//so we keep track of duplicated entries and be able to analyze them
export const logDuplicateUnifiedHistoryEntryEvent = ({
entryName,
lastEntryURL,
newEntryURL,
}: UnifiedHistoryEntryDuplicated) => {
reportInteraction(UNIFIED_HISTORY_ENTRY_DUPLICATED, {
entryName,
lastEntryURL,
newEntryURL,
});
};
//We keep track of users open and closing the drawer
export const logUnifiedHistoryDrawerInteractionEvent = ({ type }: { type: UnifiedHistoryDrawerInteraction }) => {
reportInteraction(UNIFIED_HISTORY_DRAWER_INTERACTION, {
type,
});
};
//We keep track of users clicking on the `Show more` button
export const logUnifiedHistoryShowMoreEvent = () => {
reportInteraction(UNIFIED_HISTORY_DRAWER_SHOW_MORE);
};

View File

@@ -6,7 +6,6 @@ import { Components } from '@grafana/e2e-selectors';
import { t } from '@grafana/i18n'; import { t } from '@grafana/i18n';
import { ScopesContextValue } from '@grafana/runtime'; import { ScopesContextValue } from '@grafana/runtime';
import { Icon, Stack, ToolbarButton, useStyles2 } from '@grafana/ui'; import { Icon, Stack, ToolbarButton, useStyles2 } from '@grafana/ui';
import { config } from 'app/core/config';
import { MEGA_MENU_TOGGLE_ID } from 'app/core/constants'; import { MEGA_MENU_TOGGLE_ID } from 'app/core/constants';
import { useGrafana } from 'app/core/context/GrafanaContext'; import { useGrafana } from 'app/core/context/GrafanaContext';
import { contextSrv } from 'app/core/core'; import { contextSrv } from 'app/core/core';
@@ -18,7 +17,6 @@ import { Branding } from '../../Branding/Branding';
import { Breadcrumbs } from '../../Breadcrumbs/Breadcrumbs'; import { Breadcrumbs } from '../../Breadcrumbs/Breadcrumbs';
import { buildBreadcrumbs } from '../../Breadcrumbs/utils'; import { buildBreadcrumbs } from '../../Breadcrumbs/utils';
import { ExtensionToolbarItem } from '../ExtensionSidebar/ExtensionToolbarItem'; import { ExtensionToolbarItem } from '../ExtensionSidebar/ExtensionToolbarItem';
import { HistoryContainer } from '../History/HistoryContainer';
import { NavToolbarSeparator } from '../NavToolbar/NavToolbarSeparator'; import { NavToolbarSeparator } from '../NavToolbar/NavToolbarSeparator';
import { QuickAdd } from '../QuickAdd/QuickAdd'; import { QuickAdd } from '../QuickAdd/QuickAdd';
@@ -58,7 +56,6 @@ export const SingleTopBar = memo(function SingleTopBar({
const profileNode = useSelector((state) => state.navIndex['profile']); const profileNode = useSelector((state) => state.navIndex['profile']);
const homeNav = useSelector((state) => state.navIndex)[HOME_NAV_ID]; const homeNav = useSelector((state) => state.navIndex)[HOME_NAV_ID];
const breadcrumbs = buildBreadcrumbs(sectionNav, pageNav, homeNav); const breadcrumbs = buildBreadcrumbs(sectionNav, pageNav, homeNav);
const unifiedHistoryEnabled = config.featureToggles.unifiedHistory;
const isSmallScreen = !useMediaQueryMinWidth('sm'); const isSmallScreen = !useMediaQueryMinWidth('sm');
return ( return (
@@ -91,7 +88,6 @@ export const SingleTopBar = memo(function SingleTopBar({
minWidth={{ xs: 'unset', lg: 0 }} minWidth={{ xs: 'unset', lg: 0 }}
> >
<TopSearchBarCommandPaletteTrigger /> <TopSearchBarCommandPaletteTrigger />
{unifiedHistoryEnabled && !isSmallScreen && <HistoryContainer />}
{!isSmallScreen && <QuickAdd />} {!isSmallScreen && <QuickAdd />}
<HelpTopBarButton isSmallScreen={isSmallScreen} /> <HelpTopBarButton isSmallScreen={isSmallScreen} />
<NavToolbarSeparator /> <NavToolbarSeparator />

View File

@@ -4,28 +4,3 @@ export interface ToolbarUpdateProps {
pageNav?: NavModelItem; pageNav?: NavModelItem;
actions?: React.ReactNode; actions?: React.ReactNode;
} }
export interface HistoryEntryView {
name: string;
description: string;
url: string;
time: number;
}
export interface HistoryEntrySparkline {
values: number[];
range: {
min: number;
max: number;
delta: number;
};
}
export interface HistoryEntry {
name: string;
time: number;
breadcrumbs: NavModelItem[];
url: string;
views: HistoryEntryView[];
sparklineData?: HistoryEntrySparkline;
}

View File

@@ -1,6 +1,5 @@
import { AnnotationQuery, BusEventBase, BusEventWithPayload, eventFactory } from '@grafana/data'; import { AnnotationQuery, BusEventBase, BusEventWithPayload, eventFactory } from '@grafana/data';
import { IconName, ButtonVariant } from '@grafana/ui'; import { IconName, ButtonVariant } from '@grafana/ui';
import { HistoryEntryView } from 'app/core/components/AppChrome/types';
/** /**
* Event Payloads * Event Payloads
@@ -217,7 +216,3 @@ export class PanelEditEnteredEvent extends BusEventWithPayload<number> {
export class PanelEditExitedEvent extends BusEventWithPayload<number> { export class PanelEditExitedEvent extends BusEventWithPayload<number> {
static type = 'panel-edit-finished'; static type = 'panel-edit-finished';
} }
export class RecordHistoryEntryEvent extends BusEventWithPayload<HistoryEntryView> {
static type = 'record-history-entry';
}

View File

@@ -10469,18 +10469,6 @@
"help/documentation": "Documentation", "help/documentation": "Documentation",
"help/keyboard-shortcuts": "Keyboard shortcuts", "help/keyboard-shortcuts": "Keyboard shortcuts",
"help/support": "Support", "help/support": "Support",
"history-container": {
"drawer-tittle": "History"
},
"history-wrapper": {
"collapse": "Collapse",
"expand": "Expand",
"icon-selected": "Selected Entry",
"icon-unselected": "Normal Entry",
"show-more": "Show more",
"today": "Today",
"yesterday": "Yesterday"
},
"home": { "home": {
"title": "Home" "title": "Home"
}, },