Submit
Path:
~
/
/
usr
/
share
/
grafana
/
public
/
app
/
features
/
explore
/
File Content:
CorrelationEditorModeBar.tsx
import { css } from '@emotion/css'; import React, { useEffect, useState } from 'react'; import { Prompt } from 'react-router-dom'; import { useBeforeUnload, useUnmount } from 'react-use'; import { GrafanaTheme2, colorManipulator } from '@grafana/data'; import { reportInteraction } from '@grafana/runtime'; import { Button, HorizontalGroup, Icon, Tooltip, useStyles2 } from '@grafana/ui'; import { CORRELATION_EDITOR_POST_CONFIRM_ACTION, ExploreItemState, useDispatch, useSelector } from 'app/types'; import { CorrelationUnsavedChangesModal } from './CorrelationUnsavedChangesModal'; import { showModalMessage } from './correlationEditLogic'; import { saveCurrentCorrelation } from './state/correlations'; import { changeDatasource } from './state/datasource'; import { changeCorrelationHelperData } from './state/explorePane'; import { changeCorrelationEditorDetails, splitClose } from './state/main'; import { runQueries } from './state/query'; import { selectCorrelationDetails, selectIsHelperShowing } from './state/selectors'; export const CorrelationEditorModeBar = ({ panes }: { panes: Array<[string, ExploreItemState]> }) => { const dispatch = useDispatch(); const styles = useStyles2(getStyles); const correlationDetails = useSelector(selectCorrelationDetails); const isHelperShowing = useSelector(selectIsHelperShowing); const [saveMessage, setSaveMessage] = useState<string | undefined>(undefined); // undefined means do not show // handle refreshing and closing the tab useBeforeUnload(correlationDetails?.correlationDirty || false, 'Save correlation?'); useBeforeUnload( (!correlationDetails?.correlationDirty && correlationDetails?.queryEditorDirty) || false, 'The query editor was changed. Save correlation before continuing?' ); // decide if we are displaying prompt, perform action if not useEffect(() => { if (correlationDetails?.isExiting) { const { correlationDirty, queryEditorDirty } = correlationDetails; let isActionLeft = undefined; let action = undefined; if (correlationDetails.postConfirmAction) { isActionLeft = correlationDetails.postConfirmAction.isActionLeft; action = correlationDetails.postConfirmAction.action; } else { // closing the editor only action = CORRELATION_EDITOR_POST_CONFIRM_ACTION.CLOSE_EDITOR; isActionLeft = false; } const modalMessage = showModalMessage(action, isActionLeft, correlationDirty, queryEditorDirty); if (modalMessage !== undefined) { setSaveMessage(modalMessage); } else { // if no prompt, perform action if ( action === CORRELATION_EDITOR_POST_CONFIRM_ACTION.CHANGE_DATASOURCE && correlationDetails.postConfirmAction ) { const { exploreId, changeDatasourceUid } = correlationDetails?.postConfirmAction; if (exploreId && changeDatasourceUid) { dispatch( changeDatasource({ exploreId, datasource: changeDatasourceUid, options: { importQueries: true } }) ); dispatch( changeCorrelationEditorDetails({ isExiting: false, }) ); } } else if ( action === CORRELATION_EDITOR_POST_CONFIRM_ACTION.CLOSE_PANE && correlationDetails.postConfirmAction ) { const { exploreId } = correlationDetails?.postConfirmAction; if (exploreId !== undefined) { dispatch(splitClose(exploreId)); dispatch( changeCorrelationEditorDetails({ isExiting: false, }) ); } } else if (action === CORRELATION_EDITOR_POST_CONFIRM_ACTION.CLOSE_EDITOR) { dispatch( changeCorrelationEditorDetails({ editorMode: false, }) ); } } } }, [correlationDetails, dispatch, isHelperShowing]); // clear data when unmounted useUnmount(() => { dispatch( changeCorrelationEditorDetails({ editorMode: false, isExiting: false, correlationDirty: false, label: undefined, description: undefined, canSave: false, }) ); panes.forEach((pane) => { dispatch( changeCorrelationHelperData({ exploreId: pane[0], correlationEditorHelperData: undefined, }) ); dispatch(runQueries({ exploreId: pane[0] })); }); }); const resetEditor = () => { dispatch( changeCorrelationEditorDetails({ editorMode: true, isExiting: false, correlationDirty: false, label: undefined, description: undefined, canSave: false, }) ); panes.forEach((pane) => { dispatch( changeCorrelationHelperData({ exploreId: pane[0], correlationEditorHelperData: undefined, }) ); dispatch(runQueries({ exploreId: pane[0] })); }); }; const closePane = (exploreId: string) => { setSaveMessage(undefined); dispatch(splitClose(exploreId)); reportInteraction('grafana_explore_split_view_closed'); }; const changeDatasourcePostAction = (exploreId: string, datasourceUid: string) => { setSaveMessage(undefined); dispatch(changeDatasource({ exploreId, datasource: datasourceUid, options: { importQueries: true } })); }; const saveCorrelationPostAction = (skipPostConfirmAction: boolean) => { dispatch( saveCurrentCorrelation( correlationDetails?.label, correlationDetails?.description, correlationDetails?.transformations ) ); if (!skipPostConfirmAction && correlationDetails?.postConfirmAction !== undefined) { const { exploreId, action, changeDatasourceUid } = correlationDetails?.postConfirmAction; if (action === CORRELATION_EDITOR_POST_CONFIRM_ACTION.CLOSE_PANE) { closePane(exploreId); resetEditor(); } else if ( action === CORRELATION_EDITOR_POST_CONFIRM_ACTION.CHANGE_DATASOURCE && changeDatasourceUid !== undefined ) { changeDatasource({ exploreId, datasource: changeDatasourceUid }); resetEditor(); } } else { dispatch(changeCorrelationEditorDetails({ editorMode: false, correlationDirty: false, isExiting: false })); } }; return ( <> {/* Handle navigating outside of Explore */} <Prompt message={(location) => { if ( location.pathname !== '/explore' && (correlationDetails?.editorMode || false) && (correlationDetails?.correlationDirty || false) ) { return 'You have unsaved correlation data. Continue?'; } else { return true; } }} /> {saveMessage !== undefined && ( <CorrelationUnsavedChangesModal onDiscard={() => { if (correlationDetails?.postConfirmAction !== undefined) { const { exploreId, action, changeDatasourceUid } = correlationDetails?.postConfirmAction; if (action === CORRELATION_EDITOR_POST_CONFIRM_ACTION.CLOSE_PANE) { closePane(exploreId); } else if ( action === CORRELATION_EDITOR_POST_CONFIRM_ACTION.CHANGE_DATASOURCE && changeDatasourceUid !== undefined ) { changeDatasourcePostAction(exploreId, changeDatasourceUid); } dispatch(changeCorrelationEditorDetails({ isExiting: false })); } else { // exit correlations mode // if we are discarding the in progress correlation, reset everything // this modal only shows if the editorMode is false, so we just need to update the dirty state dispatch( changeCorrelationEditorDetails({ editorMode: false, correlationDirty: false, isExiting: false, }) ); } }} onCancel={() => { // if we are cancelling the exit, set the editor mode back to true and hide the prompt dispatch(changeCorrelationEditorDetails({ isExiting: false })); setSaveMessage(undefined); }} onSave={() => { saveCorrelationPostAction(false); }} message={saveMessage} /> )} <div className={styles.correlationEditorTop}> <HorizontalGroup spacing="md" justify="flex-end"> <Tooltip content="Correlations editor in Explore is an experimental feature."> <Icon className={styles.iconColor} name="info-circle" size="xl" /> </Tooltip> <Button variant="secondary" disabled={!correlationDetails?.canSave} fill="outline" className={correlationDetails?.canSave ? styles.buttonColor : styles.disabledButtonColor} onClick={() => { saveCorrelationPostAction(true); }} > Save </Button> <Button variant="secondary" fill="outline" className={styles.buttonColor} icon="times" onClick={() => { dispatch(changeCorrelationEditorDetails({ isExiting: true })); reportInteraction('grafana_explore_correlation_editor_exit_pressed'); }} > Exit correlation editor </Button> </HorizontalGroup> </div> </> ); }; const getStyles = (theme: GrafanaTheme2) => { const contrastColor = theme.colors.getContrastText(theme.colors.primary.main); const lighterBackgroundColor = colorManipulator.lighten(theme.colors.primary.main, 0.1); const darkerBackgroundColor = colorManipulator.darken(theme.colors.primary.main, 0.2); const disabledColor = colorManipulator.darken(contrastColor, 0.2); return { correlationEditorTop: css({ backgroundColor: theme.colors.primary.main, marginTop: '3px', padding: theme.spacing(1), }), iconColor: css({ color: contrastColor, }), buttonColor: css({ color: contrastColor, borderColor: contrastColor, '&:hover': { color: contrastColor, borderColor: contrastColor, backgroundColor: lighterBackgroundColor, }, }), // important needed to override disabled state styling disabledButtonColor: css({ color: `${disabledColor} !important`, backgroundColor: `${darkerBackgroundColor} !important`, }), }; };
Edit
Rename
Chmod
Delete
FILE
FOLDER
INFO
Name
Size
Permission
Action
ContentOutline
---
0755
FlameGraph
---
0755
Graph
---
0755
Logs
---
0755
NodeGraph
---
0755
PrometheusListView
---
0755
RawPrometheus
---
0755
RichHistory
---
0755
Table
---
0755
TraceView
---
0755
__mocks__
---
0755
extensions
---
0755
hooks
---
0755
spec
---
0755
state
---
0755
utils
---
0755
CorrelationEditorModeBar.tsx
10676 bytes
0644
CorrelationHelper.tsx
9880 bytes
0644
CorrelationTransformationAddModal.tsx
8532 bytes
0644
CorrelationUnsavedChangesModal.tsx
967 bytes
0644
CustomContainer.tsx
1867 bytes
0644
ElapsedTime.tsx
942 bytes
0644
ErrorContainer.test.tsx
1737 bytes
0644
ErrorContainer.tsx
748 bytes
0644
Explore.test.tsx
6031 bytes
0644
Explore.tsx
27115 bytes
0644
ExploreActions.tsx
3705 bytes
0644
ExploreDrawer.tsx
2043 bytes
0644
ExplorePage.tsx
4146 bytes
0644
ExplorePaneContainer.tsx
2847 bytes
0644
ExploreQueryInspector.test.tsx
4831 bytes
0644
ExploreQueryInspector.tsx
3900 bytes
0644
ExploreTimeControls.tsx
3147 bytes
0644
ExploreToolbar.tsx
12603 bytes
0644
FeatureTogglePage.tsx
700 bytes
0644
LiveTailButton.tsx
2144 bytes
0644
MetaInfoText.test.tsx
1115 bytes
0644
MetaInfoText.tsx
1844 bytes
0644
NoData.tsx
921 bytes
0644
NoDataSourceCallToAction.tsx
1524 bytes
0644
QueryRows.test.tsx
2757 bytes
0644
QueryRows.tsx
3023 bytes
0644
ResponseErrorContainer.test.tsx
1958 bytes
0644
ResponseErrorContainer.tsx
636 bytes
0644
SecondaryActions.test.tsx
2734 bytes
0644
SecondaryActions.tsx
2390 bytes
0644
ShortLinkButtonMenu.tsx
4937 bytes
0644
SupplementaryResultError.test.tsx
1267 bytes
0644
SupplementaryResultError.tsx
2158 bytes
0644
Time.tsx
812 bytes
0644
TimeSyncButton.test.tsx
674 bytes
0644
TimeSyncButton.tsx
736 bytes
0644
correlationEditLogic.test.ts
5061 bytes
0644
correlationEditLogic.ts
2481 bytes
0644
useLiveTailControls.ts
2035 bytes
0644
N4ST4R_ID | Naxtarrr