mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Dashboard import: Bug fixes (#23591)
* clear dashboard on unmount * fix menu z-index, folderpicker width * fix issue with saving dashboard in another folder * use foldermodel instead of selectablevalue * using z-index from theme * updated names * update snapshot * remove size from folderpicker * use connectWithCleanup * update snapshot
This commit is contained in:
parent
e16213724c
commit
4183921c62
@ -332,6 +332,8 @@ export function SelectBase<T>({
|
|||||||
}),
|
}),
|
||||||
container: () => ({
|
container: () => ({
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
|
// This puts the menu above Inputs (z-index: 1)
|
||||||
|
zIndex: theme.zIndex.dropdown,
|
||||||
width: width ? `${8 * width}px` : '100%',
|
width: width ? `${8 * width}px` : '100%',
|
||||||
}),
|
}),
|
||||||
}}
|
}}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import React, { FormEvent, PureComponent } from 'react';
|
import React, { FormEvent, PureComponent } from 'react';
|
||||||
import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux';
|
import { MapDispatchToProps, MapStateToProps } from 'react-redux';
|
||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
import { AppEvents, NavModel } from '@grafana/data';
|
import { AppEvents, NavModel } from '@grafana/data';
|
||||||
import { Button, stylesFactory, Input, TextArea, Field, Form, Legend } from '@grafana/ui';
|
import { Button, stylesFactory, Input, TextArea, Field, Form, Legend } from '@grafana/ui';
|
||||||
import Page from 'app/core/components/Page/Page';
|
import Page from 'app/core/components/Page/Page';
|
||||||
|
import { connectWithCleanUp } from 'app/core/components/connectWithCleanUp';
|
||||||
import { ImportDashboardOverview } from './components/ImportDashboardOverview';
|
import { ImportDashboardOverview } from './components/ImportDashboardOverview';
|
||||||
import { DashboardFileUpload } from './components/DashboardFileUpload';
|
import { DashboardFileUpload } from './components/DashboardFileUpload';
|
||||||
import { validateDashboardJson, validateGcomDashboard } from './utils/validation';
|
import { validateDashboardJson, validateGcomDashboard } from './utils/validation';
|
||||||
@ -142,7 +143,11 @@ const mapDispatchToProps: MapDispatchToProps<DispatchProps, Props> = {
|
|||||||
importDashboardJson,
|
importDashboardJson,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DashboardImportPage = connect(mapStateToProps, mapDispatchToProps)(DashboardImportUnConnected);
|
export const DashboardImportPage = connectWithCleanUp(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps,
|
||||||
|
state => state.importDashboard
|
||||||
|
)(DashboardImportUnConnected);
|
||||||
export default DashboardImportPage;
|
export default DashboardImportPage;
|
||||||
DashboardImportPage.displayName = 'DashboardImport';
|
DashboardImportPage.displayName = 'DashboardImport';
|
||||||
|
|
||||||
|
@ -58,18 +58,12 @@ export const ImportDashboardForm: FC<Props> = ({
|
|||||||
type="text"
|
type="text"
|
||||||
ref={register({
|
ref={register({
|
||||||
required: 'Name is required',
|
required: 'Name is required',
|
||||||
validate: async (v: string) => await validateTitle(v, getValues().folderId),
|
validate: async (v: string) => await validateTitle(v, getValues().folder.id),
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</Field>
|
</Field>
|
||||||
<Field label="Folder">
|
<Field label="Folder">
|
||||||
<InputControl
|
<InputControl as={FolderPicker} name="folder" useNewForms initialFolderId={initialFolderId} control={control} />
|
||||||
as={FolderPicker}
|
|
||||||
name="folderId"
|
|
||||||
useNewForms
|
|
||||||
initialFolderId={initialFolderId}
|
|
||||||
control={control}
|
|
||||||
/>
|
|
||||||
</Field>
|
</Field>
|
||||||
<Field
|
<Field
|
||||||
label="Unique identifier (uid)"
|
label="Unique identifier (uid)"
|
||||||
|
@ -3,7 +3,7 @@ import { dateTime } from '@grafana/data';
|
|||||||
import { Forms, Form } from '@grafana/ui';
|
import { Forms, Form } from '@grafana/ui';
|
||||||
import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux';
|
import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux';
|
||||||
import { ImportDashboardForm } from './ImportDashboardForm';
|
import { ImportDashboardForm } from './ImportDashboardForm';
|
||||||
import { resetDashboard, saveDashboard } from '../state/actions';
|
import { clearLoadedDashboard, saveDashboard } from '../state/actions';
|
||||||
import { DashboardInputs, DashboardSource, ImportDashboardDTO } from '../state/reducers';
|
import { DashboardInputs, DashboardSource, ImportDashboardDTO } from '../state/reducers';
|
||||||
import { StoreState } from 'app/types';
|
import { StoreState } from 'app/types';
|
||||||
|
|
||||||
@ -14,11 +14,11 @@ interface ConnectedProps {
|
|||||||
inputs: DashboardInputs;
|
inputs: DashboardInputs;
|
||||||
source: DashboardSource;
|
source: DashboardSource;
|
||||||
meta?: any;
|
meta?: any;
|
||||||
folderId: number;
|
folder: { id: number; title?: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DispatchProps {
|
interface DispatchProps {
|
||||||
resetDashboard: typeof resetDashboard;
|
clearLoadedDashboard: typeof clearLoadedDashboard;
|
||||||
saveDashboard: typeof saveDashboard;
|
saveDashboard: typeof saveDashboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ class ImportDashboardOverviewUnConnected extends PureComponent<Props, State> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onCancel = () => {
|
onCancel = () => {
|
||||||
this.props.resetDashboard();
|
this.props.clearLoadedDashboard();
|
||||||
};
|
};
|
||||||
|
|
||||||
onUidReset = () => {
|
onUidReset = () => {
|
||||||
@ -46,7 +46,7 @@ class ImportDashboardOverviewUnConnected extends PureComponent<Props, State> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { dashboard, inputs, meta, source, folderId } = this.props;
|
const { dashboard, inputs, meta, source, folder } = this.props;
|
||||||
const { uidReset } = this.state;
|
const { uidReset } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -81,7 +81,7 @@ class ImportDashboardOverviewUnConnected extends PureComponent<Props, State> {
|
|||||||
)}
|
)}
|
||||||
<Form
|
<Form
|
||||||
onSubmit={this.onSubmit}
|
onSubmit={this.onSubmit}
|
||||||
defaultValues={{ ...dashboard, constants: [], dataSources: [], folderId }}
|
defaultValues={{ ...dashboard, constants: [], dataSources: [], folder: folder }}
|
||||||
validateOnMount
|
validateOnMount
|
||||||
validateFieldsOnMount={['title', 'uid']}
|
validateFieldsOnMount={['title', 'uid']}
|
||||||
validateOn="onChange"
|
validateOn="onChange"
|
||||||
@ -97,7 +97,7 @@ class ImportDashboardOverviewUnConnected extends PureComponent<Props, State> {
|
|||||||
onCancel={this.onCancel}
|
onCancel={this.onCancel}
|
||||||
onUidReset={this.onUidReset}
|
onUidReset={this.onUidReset}
|
||||||
onSubmit={this.onSubmit}
|
onSubmit={this.onSubmit}
|
||||||
initialFolderId={folderId}
|
initialFolderId={folder.id}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Form>
|
</Form>
|
||||||
@ -111,11 +111,11 @@ const mapStateToProps: MapStateToProps<ConnectedProps, OwnProps, StoreState> = (
|
|||||||
meta: state.importDashboard.meta,
|
meta: state.importDashboard.meta,
|
||||||
source: state.importDashboard.source,
|
source: state.importDashboard.source,
|
||||||
inputs: state.importDashboard.inputs,
|
inputs: state.importDashboard.inputs,
|
||||||
folderId: state.location.routeParams.folderId ? Number(state.location.routeParams.folderId) : 0,
|
folder: state.location.routeParams.folderId ? { id: Number(state.location.routeParams.folderId) } : { id: 0 },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps: MapDispatchToProps<DispatchProps, OwnProps> = {
|
const mapDispatchToProps: MapDispatchToProps<DispatchProps, OwnProps> = {
|
||||||
resetDashboard,
|
clearLoadedDashboard,
|
||||||
saveDashboard,
|
saveDashboard,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ function processInputs(dashboardJson: any): ThunkResult<void> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resetDashboard(): ThunkResult<void> {
|
export function clearLoadedDashboard(): ThunkResult<void> {
|
||||||
return dispatch => {
|
return dispatch => {
|
||||||
dispatch(clearDashboard());
|
dispatch(clearDashboard());
|
||||||
};
|
};
|
||||||
@ -96,7 +96,7 @@ export function saveDashboard(importDashboardForm: ImportDashboardDTO): ThunkRes
|
|||||||
dashboard: { ...dashboard, title: importDashboardForm.title, uid: importDashboardForm.uid },
|
dashboard: { ...dashboard, title: importDashboardForm.title, uid: importDashboardForm.uid },
|
||||||
overwrite: true,
|
overwrite: true,
|
||||||
inputs: inputsToPersist,
|
inputs: inputsToPersist,
|
||||||
folderId: importDashboardForm.folderId,
|
folderId: importDashboardForm.folder.id,
|
||||||
});
|
});
|
||||||
const dashboardUrl = locationUtil.stripBaseFromUrl(result.importedUrl);
|
const dashboardUrl = locationUtil.stripBaseFromUrl(result.importedUrl);
|
||||||
dispatch(updateLocation({ path: dashboardUrl }));
|
dispatch(updateLocation({ path: dashboardUrl }));
|
||||||
|
@ -12,7 +12,7 @@ export interface ImportDashboardDTO {
|
|||||||
gnetId: string;
|
gnetId: string;
|
||||||
constants: string[];
|
constants: string[];
|
||||||
dataSources: DataSourceSelectItem[];
|
dataSources: DataSourceSelectItem[];
|
||||||
folderId: number;
|
folder: { id: number; title?: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum InputType {
|
export enum InputType {
|
||||||
|
Loading…
Reference in New Issue
Block a user