mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Prompt DS modal when the user adds the first panel to a dashboard (#66911)
* Prompt DS modal when the user adds the first panel to a dashboard * Rename state prop and use toggle * Change modal size * Avoid flickering for dashboard modal when changing number of results * When editing panel 1, only display when new dashboard
This commit is contained in:
parent
4d2570ad72
commit
40c7b3126e
@ -8,6 +8,7 @@ import { usePopper } from 'react-popper';
|
||||
import { DataSourceInstanceSettings, GrafanaTheme2 } from '@grafana/data';
|
||||
import { DataSourceJsonData } from '@grafana/schema';
|
||||
import { Button, CustomScrollbar, Icon, Input, ModalsController, Portal, useStyles2 } from '@grafana/ui';
|
||||
import config from 'app/core/config';
|
||||
|
||||
import { DataSourceList } from './DataSourceList';
|
||||
import { DataSourceLogo, DataSourceLogoPlaceHolder } from './DataSourceLogo';
|
||||
@ -157,7 +158,7 @@ const PickerContent = React.forwardRef<HTMLDivElement, PickerContentProps>((prop
|
||||
</div>
|
||||
|
||||
<div className={styles.footer}>
|
||||
{onClickAddCSV && (
|
||||
{onClickAddCSV && config.featureToggles.editPanelCSVDragAndDrop && (
|
||||
<Button variant="secondary" size="sm" onClick={clickAddCSVCallback}>
|
||||
Add csv or spreadsheet
|
||||
</Button>
|
||||
|
@ -43,64 +43,62 @@ export function DataSourceModal({
|
||||
closeOnBackdropClick={true}
|
||||
isOpen={true}
|
||||
className={styles.modal}
|
||||
contentClassName={styles.modalContent}
|
||||
onClickBackdrop={onDismiss}
|
||||
onDismiss={onDismiss}
|
||||
>
|
||||
<div className={styles.modalContent}>
|
||||
<div className={styles.leftColumn}>
|
||||
<Input
|
||||
className={styles.searchInput}
|
||||
value={search}
|
||||
prefix={<Icon name="search" />}
|
||||
placeholder="Search data source"
|
||||
onChange={(e) => setSearch(e.currentTarget.value)}
|
||||
<div className={styles.leftColumn}>
|
||||
<Input
|
||||
className={styles.searchInput}
|
||||
value={search}
|
||||
prefix={<Icon name="search" />}
|
||||
placeholder="Search data source"
|
||||
onChange={(e) => setSearch(e.currentTarget.value)}
|
||||
/>
|
||||
<CustomScrollbar>
|
||||
<DataSourceList
|
||||
dashboard={false}
|
||||
mixed={false}
|
||||
variables
|
||||
filter={(ds) => ds.name.includes(search) && !ds.meta.builtIn}
|
||||
onChange={onChange}
|
||||
current={current}
|
||||
/>
|
||||
<CustomScrollbar>
|
||||
<DataSourceList
|
||||
dashboard={false}
|
||||
mixed={false}
|
||||
variables
|
||||
// FIXME: Filter out the grafana data source in a hacky way
|
||||
filter={(ds) => ds.name.toLowerCase().includes(search.toLowerCase()) && ds.name !== '-- Grafana --'}
|
||||
onChange={onChange}
|
||||
current={current}
|
||||
/>
|
||||
</CustomScrollbar>
|
||||
</CustomScrollbar>
|
||||
</div>
|
||||
<div className={styles.rightColumn}>
|
||||
<div className={styles.builtInDataSources}>
|
||||
<DataSourceList
|
||||
className={styles.builtInDataSourceList}
|
||||
filter={(ds) => !!ds.meta.builtIn}
|
||||
dashboard
|
||||
mixed
|
||||
onChange={onChange}
|
||||
current={current}
|
||||
/>
|
||||
{enableFileUpload && (
|
||||
<FileDropzone
|
||||
readAs="readAsArrayBuffer"
|
||||
fileListRenderer={() => undefined}
|
||||
options={{
|
||||
maxSize: DFImport.maxFileSize,
|
||||
multiple: false,
|
||||
accept: DFImport.acceptedFiles,
|
||||
...fileUploadOptions,
|
||||
onDrop: (...args) => {
|
||||
fileUploadOptions?.onDrop?.(...args);
|
||||
onDismiss();
|
||||
},
|
||||
}}
|
||||
>
|
||||
<FileDropzoneDefaultChildren />
|
||||
</FileDropzone>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.rightColumn}>
|
||||
<div className={styles.builtInDataSources}>
|
||||
<DataSourceList
|
||||
className={styles.builtInDataSourceList}
|
||||
filter={(ds) => !!ds.meta.builtIn}
|
||||
dashboard
|
||||
mixed
|
||||
onChange={onChange}
|
||||
current={current}
|
||||
/>
|
||||
{enableFileUpload && (
|
||||
<FileDropzone
|
||||
readAs="readAsArrayBuffer"
|
||||
fileListRenderer={() => undefined}
|
||||
options={{
|
||||
maxSize: DFImport.maxFileSize,
|
||||
multiple: false,
|
||||
accept: DFImport.acceptedFiles,
|
||||
...fileUploadOptions,
|
||||
onDrop: (...args) => {
|
||||
fileUploadOptions?.onDrop?.(...args);
|
||||
onDismiss();
|
||||
},
|
||||
}}
|
||||
>
|
||||
<FileDropzoneDefaultChildren />
|
||||
</FileDropzone>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.dsCTAs}>
|
||||
<LinkButton variant="secondary" href={`datasources/new`}>
|
||||
Configure a new data source
|
||||
</LinkButton>
|
||||
</div>
|
||||
<div className={styles.dsCTAs}>
|
||||
<LinkButton variant="secondary" href={`datasources/new`}>
|
||||
Configure a new data source
|
||||
</LinkButton>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
@ -112,12 +110,12 @@ function getDataSourceModalStyles(theme: GrafanaTheme2) {
|
||||
modal: css`
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
max-width: 1200px;
|
||||
max-height: 900px;
|
||||
`,
|
||||
modalContent: css`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: stretch;
|
||||
height: 100%;
|
||||
`,
|
||||
leftColumn: css`
|
||||
@ -133,7 +131,6 @@ function getDataSourceModalStyles(theme: GrafanaTheme2) {
|
||||
flex-direction: column;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
padding: ${theme.spacing(1)};
|
||||
justify-items: space-evenly;
|
||||
align-items: stretch;
|
||||
padding-left: ${theme.spacing(1)};
|
||||
|
@ -15,13 +15,14 @@ import {
|
||||
PanelData,
|
||||
} from '@grafana/data';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { getDataSourceSrv } from '@grafana/runtime';
|
||||
import { getDataSourceSrv, locationService } from '@grafana/runtime';
|
||||
import { Button, CustomScrollbar, HorizontalGroup, InlineFormLabel, Modal, stylesFactory } from '@grafana/ui';
|
||||
import { PluginHelp } from 'app/core/components/PluginHelp/PluginHelp';
|
||||
import config from 'app/core/config';
|
||||
import { backendSrv } from 'app/core/services/backend_srv';
|
||||
import { addQuery, queryIsEmpty } from 'app/core/utils/query';
|
||||
import * as DFImport from 'app/features/dataframe-import';
|
||||
import { DataSourceModal } from 'app/features/datasources/components/picker/DataSourceModal';
|
||||
import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker';
|
||||
import { dataSource as expressionDatasource } from 'app/features/expressions/ExpressionDatasource';
|
||||
import { DashboardQueryEditor, isSharedDashboardQuery } from 'app/plugins/datasource/dashboard';
|
||||
@ -51,6 +52,7 @@ interface State {
|
||||
isLoadingHelp: boolean;
|
||||
isPickerOpen: boolean;
|
||||
isAddingMixed: boolean;
|
||||
isDataSourceModalOpen: boolean;
|
||||
data: PanelData;
|
||||
isHelpOpen: boolean;
|
||||
defaultDataSource?: DataSourceApi;
|
||||
@ -69,6 +71,7 @@ export class QueryGroup extends PureComponent<Props, State> {
|
||||
querySubscription: Unsubscribable | null = null;
|
||||
|
||||
state: State = {
|
||||
isDataSourceModalOpen: false,
|
||||
isLoadingHelp: false,
|
||||
helpContent: null,
|
||||
isPickerOpen: false,
|
||||
@ -116,6 +119,11 @@ export class QueryGroup extends PureComponent<Props, State> {
|
||||
dataSource: { ...options.dataSource },
|
||||
savedQueryUid: options.savedQueryUid,
|
||||
},
|
||||
// TODO: Detect the first panel added into a new dashboard better.
|
||||
// This is flaky in case the UID is generated differently
|
||||
isDataSourceModalOpen:
|
||||
locationService.getLocation().pathname === '/dashboard/new' &&
|
||||
locationService.getSearchObject().editPanel === '1',
|
||||
});
|
||||
} catch (error) {
|
||||
console.log('failed to load data source', error);
|
||||
@ -213,24 +221,7 @@ export class QueryGroup extends PureComponent<Props, State> {
|
||||
<InlineFormLabel htmlFor="data-source-picker" width={'auto'}>
|
||||
Data source
|
||||
</InlineFormLabel>
|
||||
<div className={styles.dataSourceRowItem}>
|
||||
<DataSourcePicker
|
||||
onChange={this.onChangeDataSource}
|
||||
current={options.dataSource}
|
||||
metrics={true}
|
||||
mixed={true}
|
||||
dashboard={true}
|
||||
variables={true}
|
||||
enableFileUpload={config.featureToggles.editPanelCSVDragAndDrop}
|
||||
fileUploadOptions={{
|
||||
onDrop: this.onFileDrop,
|
||||
maxSize: DFImport.maxFileSize,
|
||||
multiple: false,
|
||||
accept: DFImport.acceptedFiles,
|
||||
}}
|
||||
onClickAddCSV={this.onClickAddCSV}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.dataSourceRowItem}>{this.renderDataSourcePickerWithPrompt()}</div>
|
||||
{dataSource && (
|
||||
<>
|
||||
<div className={styles.dataSourceRowItem}>
|
||||
@ -290,6 +281,42 @@ export class QueryGroup extends PureComponent<Props, State> {
|
||||
);
|
||||
};
|
||||
|
||||
renderDataSourcePickerWithPrompt = () => {
|
||||
const { isDataSourceModalOpen } = this.state;
|
||||
|
||||
const commonProps = {
|
||||
enableFileUpload: config.featureToggles.editPanelCSVDragAndDrop,
|
||||
fileUploadOptions: {
|
||||
onDrop: this.onFileDrop,
|
||||
maxSize: DFImport.maxFileSize,
|
||||
multiple: false,
|
||||
accept: DFImport.acceptedFiles,
|
||||
},
|
||||
current: this.props.options.dataSource,
|
||||
onChange: (ds: DataSourceInstanceSettings) => {
|
||||
this.onChangeDataSource(ds);
|
||||
this.setState({ isDataSourceModalOpen: false });
|
||||
},
|
||||
};
|
||||
const onDismiss = () => this.setState({ isDataSourceModalOpen: false });
|
||||
|
||||
return (
|
||||
<>
|
||||
{isDataSourceModalOpen && config.featureToggles.advancedDataSourcePicker && (
|
||||
<DataSourceModal {...commonProps} onDismiss={onDismiss}></DataSourceModal>
|
||||
)}
|
||||
<DataSourcePicker
|
||||
{...commonProps}
|
||||
metrics={true}
|
||||
mixed={true}
|
||||
dashboard={true}
|
||||
variables={true}
|
||||
onClickAddCSV={this.onClickAddCSV}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
onAddMixedQuery = (datasource: any) => {
|
||||
this.onAddQuery({ datasource: datasource.name });
|
||||
this.setState({ isAddingMixed: false });
|
||||
|
Loading…
Reference in New Issue
Block a user