diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index 04137b73699..fefbf338451 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -46,6 +46,7 @@ export interface FeatureToggles { dashboardComments?: boolean; annotationComments?: boolean; migrationLocking?: boolean; + saveDashboardDrawer?: boolean; storage?: boolean; storageLocalUpload?: boolean; azureMonitorResourcePickerForMetrics?: boolean; diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index d9bebce3bfd..a4e0ba715a9 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -162,6 +162,11 @@ var ( Description: "Lock database during migrations", State: FeatureStateBeta, }, + { + Name: "saveDashboardDrawer", + Description: "Use a drawer to show save dashboard dialog", + State: FeatureStateBeta, + }, { Name: "storage", Description: "Configurable storage for dashboards, datasources, and resources", diff --git a/pkg/services/featuremgmt/toggles_gen.go b/pkg/services/featuremgmt/toggles_gen.go index 4cbd538088c..2a51f5e9833 100644 --- a/pkg/services/featuremgmt/toggles_gen.go +++ b/pkg/services/featuremgmt/toggles_gen.go @@ -123,6 +123,10 @@ const ( // Lock database during migrations FlagMigrationLocking = "migrationLocking" + // FlagSaveDashboardDrawer + // Use a drawer to show save dashboard dialog + FlagSaveDashboardDrawer = "saveDashboardDrawer" + // FlagStorage // Configurable storage for dashboards, datasources, and resources FlagStorage = "storage" diff --git a/public/app/core/services/keybindingSrv.ts b/public/app/core/services/keybindingSrv.ts index b96ef66c835..598f8448fc6 100644 --- a/public/app/core/services/keybindingSrv.ts +++ b/public/app/core/services/keybindingSrv.ts @@ -6,7 +6,7 @@ import appEvents from 'app/core/app_events'; import { getExploreUrl } from 'app/core/utils/explore'; import { DashboardModel } from 'app/features/dashboard/state'; import { ShareModal } from 'app/features/dashboard/components/ShareModal'; -import { SaveDashboardDrawer } from 'app/features/dashboard/components/SaveDashboard/SaveDashboardDrawer'; +import { SaveDashboardProxy } from 'app/features/dashboard/components/SaveDashboard/SaveDashboardProxy'; import { locationService } from '@grafana/runtime'; import { exitKioskMode, toggleKioskMode } from '../navigation/kiosk'; import { @@ -201,7 +201,7 @@ export class KeybindingSrv { if (dashboard.meta.canSave) { appEvents.publish( new ShowModalReactEvent({ - component: SaveDashboardDrawer, + component: SaveDashboardProxy, props: { dashboard, }, diff --git a/public/app/features/dashboard/components/DashNav/DashNav.tsx b/public/app/features/dashboard/components/DashNav/DashNav.tsx index b4426369ecb..084e52ed1b3 100644 --- a/public/app/features/dashboard/components/DashNav/DashNav.tsx +++ b/public/app/features/dashboard/components/DashNav/DashNav.tsx @@ -15,7 +15,7 @@ import { updateTimeZoneForSession } from 'app/features/profile/state/reducers'; import { DashboardModel } from '../../state'; import { KioskMode } from 'app/types'; import { ShareModal } from 'app/features/dashboard/components/ShareModal'; -import { SaveDashboardDrawer } from 'app/features/dashboard/components/SaveDashboard/SaveDashboardDrawer'; +import { SaveDashboardProxy } from 'app/features/dashboard/components/SaveDashboard/SaveDashboardProxy'; import { DashboardCommentsModal } from 'app/features/dashboard/components/DashboardComments/DashboardCommentsModal'; import { locationService } from '@grafana/runtime'; import { toggleKioskMode } from 'app/core/navigation/kiosk'; @@ -227,7 +227,7 @@ export const DashNav = React.memo((props) => { tooltip="Save dashboard" icon="save" onClick={() => { - showModal(SaveDashboardDrawer, { + showModal(SaveDashboardProxy, { dashboard, onDismiss: hideModal, }); diff --git a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx index bdef1ca6501..7939e89f415 100644 --- a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx +++ b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx @@ -25,7 +25,7 @@ import { DashNavTimeControls } from '../DashNav/DashNavTimeControls'; import { OptionsPane } from './OptionsPane'; import { SubMenuItems } from 'app/features/dashboard/components/SubMenu/SubMenuItems'; import { SplitPaneWrapper } from 'app/core/components/SplitPaneWrapper/SplitPaneWrapper'; -import { SaveDashboardDrawer } from '../SaveDashboard/SaveDashboardDrawer'; +import { SaveDashboardProxy } from '../SaveDashboard/SaveDashboardProxy'; import { DashboardPanel } from '../../dashgrid/DashboardPanel'; import { discardPanelChanges, initPanelEditor, updatePanelEditorUIState } from './state/actions'; @@ -145,7 +145,7 @@ export class PanelEditorUnconnected extends PureComponent { onSaveDashboard = () => { appEvents.publish( new ShowModalReactEvent({ - component: SaveDashboardDrawer, + component: SaveDashboardProxy, props: { dashboard: this.props.dashboard }, }) ); diff --git a/public/app/features/dashboard/components/SaveDashboard/SaveDashboardAsModal.tsx b/public/app/features/dashboard/components/SaveDashboard/SaveDashboardAsModal.tsx new file mode 100644 index 00000000000..ca9c0364b7c --- /dev/null +++ b/public/app/features/dashboard/components/SaveDashboard/SaveDashboardAsModal.tsx @@ -0,0 +1,50 @@ +import React, { useState } from 'react'; +import { css } from '@emotion/css'; +import { Modal } from '@grafana/ui'; +import { SaveDashboardAsForm } from './forms/SaveDashboardAsForm'; +import { SaveDashboardErrorProxy } from './SaveDashboardErrorProxy'; +import { useDashboardSave } from './useDashboardSave'; +import { SaveDashboardModalProps } from './types'; + +export const SaveDashboardAsModal: React.FC< + SaveDashboardModalProps & { + isNew?: boolean; + } +> = ({ dashboard, onDismiss, isNew }) => { + const { state, onDashboardSave } = useDashboardSave(dashboard); + const [dashboardSaveModelClone, setDashboardSaveModelClone] = useState(); + return ( + <> + {state.error && ( + + )} + {!state.error && ( + + { + setDashboardSaveModelClone(clone); + return onDashboardSave(clone, options, dashboard); + }} + isNew={isNew} + /> + + )} + + ); +}; diff --git a/public/app/features/dashboard/components/SaveDashboard/SaveDashboardButton.tsx b/public/app/features/dashboard/components/SaveDashboard/SaveDashboardButton.tsx index 3e3b19780d5..d754fe352a4 100644 --- a/public/app/features/dashboard/components/SaveDashboard/SaveDashboardButton.tsx +++ b/public/app/features/dashboard/components/SaveDashboard/SaveDashboardButton.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Button, ButtonVariant, ModalsController, FullWidthButtonContainer } from '@grafana/ui'; import { DashboardModel } from 'app/features/dashboard/state'; -import { SaveDashboardDrawer } from './SaveDashboardDrawer'; +import { SaveDashboardProxy } from './SaveDashboardProxy'; import { selectors } from '@grafana/e2e-selectors'; interface SaveDashboardButtonProps { @@ -16,7 +16,7 @@ export const SaveDashboardButton: React.FC = ({ dashbo return (