grafana/public/app/features/dashboard-scene/saving/useSaveDashboard.ts

107 lines
3.6 KiB
TypeScript

import { useAsyncFn } from 'react-use';
import { locationUtil } from '@grafana/data';
import { t } from '@grafana/i18n';
import { locationService, reportInteraction } from '@grafana/runtime';
import { Dashboard } from '@grafana/schema';
import { Spec as DashboardV2Spec } from '@grafana/schema/dist/esm/schema/dashboard/v2';
import appEvents from 'app/core/app_events';
import { useAppNotification } from 'app/core/copy/appNotification';
import { updateDashboardName } from 'app/core/reducers/navBarTree';
import { useSaveDashboardMutation } from 'app/features/browse-dashboards/api/browseDashboardsAPI';
import { SaveDashboardAsOptions, SaveDashboardOptions } from 'app/features/dashboard/components/SaveDashboard/types';
import { DashboardSavedEvent } from 'app/types/events';
import { useDispatch } from 'app/types/store';
import { updateDashboardUidLastUsedDatasource } from '../../dashboard/utils/dashboard';
import { DashboardScene } from '../scene/DashboardScene';
export function useSaveDashboard(isCopy = false) {
const dispatch = useDispatch();
const notifyApp = useAppNotification();
const [saveDashboardRtkQuery] = useSaveDashboardMutation();
const [state, onSaveDashboard] = useAsyncFn(
async (
scene: DashboardScene,
options: SaveDashboardOptions &
SaveDashboardAsOptions & {
// When provided, will take precedence over the scene's save model
rawDashboardJSON?: Dashboard | DashboardV2Spec;
}
) => {
{
let saveModel = options.rawDashboardJSON ?? scene.getSaveModel();
if (options.saveAsCopy) {
saveModel = scene.getSaveAsModel({
isNew: options.isNew,
title: options.title,
description: options.description,
copyTags: options.copyTags,
});
}
const result = await saveDashboardRtkQuery({
dashboard: saveModel,
folderUid: options.folderUid,
message: options.message,
overwrite: options.overwrite,
showErrorAlert: false,
k8s: options.k8s,
});
if ('error' in result) {
throw result.error;
}
const resultData = result.data;
scene.saveCompleted(saveModel, resultData, options.folderUid);
// important that these happen before location redirect below
appEvents.publish(new DashboardSavedEvent());
notifyApp.success(t('dashboard-scene.use-save-dashboard.message-dashboard-saved', 'Dashboard saved'));
//Update local storage dashboard to handle things like last used datasource
updateDashboardUidLastUsedDatasource(resultData.uid);
if (isCopy) {
reportInteraction('grafana_dashboard_copied', {
name: saveModel.title,
url: resultData.url,
});
} else {
reportInteraction(`grafana_dashboard_${options.isNew ? 'created' : 'saved'}`, {
name: saveModel.title,
url: resultData.url,
});
}
const currentLocation = locationService.getLocation();
const newUrl = locationUtil.stripBaseFromUrl(resultData.url);
if (newUrl !== currentLocation.pathname) {
setTimeout(() => {
locationService.push({ pathname: newUrl, search: currentLocation.search });
});
}
if (scene.state.meta.isStarred) {
dispatch(
updateDashboardName({
id: resultData.uid,
title: scene.state.title,
url: newUrl,
})
);
}
return result.data;
}
},
[dispatch, notifyApp]
);
return { state, onSaveDashboard };
}