123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- import { DataSourceInstanceSettings, locationUtil } from '@grafana/data';
- import { getDataSourceSrv, locationService, getBackendSrv } from '@grafana/runtime';
- import { notifyApp } from 'app/core/actions';
- import { createErrorNotification } from 'app/core/copy/appNotification';
- import { dashboardWatcher } from 'app/features/live/dashboard/dashboardWatcher';
- import { DashboardDataDTO, DashboardDTO, FolderInfo, PermissionLevelString, ThunkResult } from 'app/types';
- import { LibraryElementExport } from '../../dashboard/components/DashExportModal/DashboardExporter';
- import { getLibraryPanel } from '../../library-panels/state/api';
- import { LibraryElementDTO, LibraryElementKind } from '../../library-panels/types';
- import { DashboardSearchHit } from '../../search/types';
- import {
- clearDashboard,
- fetchDashboard,
- fetchFailed,
- ImportDashboardDTO,
- InputType,
- LibraryPanelInput,
- LibraryPanelInputState,
- setGcomDashboard,
- setInputs,
- setJsonDashboard,
- setLibraryPanelInputs,
- } from './reducers';
- export function fetchGcomDashboard(id: string): ThunkResult<void> {
- return async (dispatch) => {
- try {
- dispatch(fetchDashboard());
- const dashboard = await getBackendSrv().get(`/api/gnet/dashboards/${id}`);
- dispatch(setGcomDashboard(dashboard));
- dispatch(processInputs(dashboard.json));
- dispatch(processElements(dashboard.json));
- } catch (error) {
- dispatch(fetchFailed());
- dispatch(notifyApp(createErrorNotification(error.data.message || error)));
- }
- };
- }
- export function importDashboardJson(dashboard: any): ThunkResult<void> {
- return async (dispatch) => {
- dispatch(setJsonDashboard(dashboard));
- dispatch(processInputs(dashboard));
- dispatch(processElements(dashboard));
- };
- }
- function processInputs(dashboardJson: any): ThunkResult<void> {
- return (dispatch) => {
- if (dashboardJson && dashboardJson.__inputs) {
- const inputs: any[] = [];
- dashboardJson.__inputs.forEach((input: any) => {
- const inputModel: any = {
- name: input.name,
- label: input.label,
- info: input.description,
- value: input.value,
- type: input.type,
- pluginId: input.pluginId,
- options: [],
- };
- if (input.type === InputType.DataSource) {
- getDataSourceOptions(input, inputModel);
- } else if (!inputModel.info) {
- inputModel.info = 'Specify a string constant';
- }
- inputs.push(inputModel);
- });
- dispatch(setInputs(inputs));
- }
- };
- }
- function processElements(dashboardJson?: { __elements?: Record<string, LibraryElementExport> }): ThunkResult<void> {
- return async function (dispatch) {
- if (!dashboardJson || !dashboardJson.__elements) {
- return;
- }
- const libraryPanelInputs: LibraryPanelInput[] = [];
- for (const element of Object.values(dashboardJson.__elements)) {
- if (element.kind !== LibraryElementKind.Panel) {
- continue;
- }
- const model = element.model;
- const { type, description } = model;
- const { uid, name } = element;
- const input: LibraryPanelInput = {
- model: {
- model,
- uid,
- name,
- version: 0,
- meta: {},
- id: 0,
- type,
- kind: LibraryElementKind.Panel,
- description,
- } as LibraryElementDTO,
- state: LibraryPanelInputState.New,
- };
- try {
- const panelInDb = await getLibraryPanel(uid, true);
- input.state = LibraryPanelInputState.Exists;
- input.model = panelInDb;
- } catch (e: any) {
- if (e.status !== 404) {
- throw e;
- }
- }
- libraryPanelInputs.push(input);
- }
- dispatch(setLibraryPanelInputs(libraryPanelInputs));
- };
- }
- export function clearLoadedDashboard(): ThunkResult<void> {
- return (dispatch) => {
- dispatch(clearDashboard());
- };
- }
- export function importDashboard(importDashboardForm: ImportDashboardDTO): ThunkResult<void> {
- return async (dispatch, getState) => {
- const dashboard = getState().importDashboard.dashboard;
- const inputs = getState().importDashboard.inputs;
- let inputsToPersist = [] as any[];
- importDashboardForm.dataSources?.forEach((dataSource: DataSourceInstanceSettings, index: number) => {
- const input = inputs.dataSources[index];
- inputsToPersist.push({
- name: input.name,
- type: input.type,
- pluginId: input.pluginId,
- value: dataSource.uid,
- });
- });
- importDashboardForm.constants?.forEach((constant: any, index: number) => {
- const input = inputs.constants[index];
- inputsToPersist.push({
- value: constant,
- name: input.name,
- type: input.type,
- });
- });
- const result = await getBackendSrv().post('api/dashboards/import', {
- // uid: if user changed it, take the new uid from importDashboardForm,
- // else read it from original dashboard
- // by default the uid input is disabled, onSubmit ignores values from disabled inputs
- dashboard: { ...dashboard, title: importDashboardForm.title, uid: importDashboardForm.uid || dashboard.uid },
- overwrite: true,
- inputs: inputsToPersist,
- folderId: importDashboardForm.folder.id,
- });
- const dashboardUrl = locationUtil.stripBaseFromUrl(result.importedUrl);
- locationService.push(dashboardUrl);
- };
- }
- const getDataSourceOptions = (input: { pluginId: string; pluginName: string }, inputModel: any) => {
- const sources = getDataSourceSrv().getList({ pluginId: input.pluginId });
- if (sources.length === 0) {
- inputModel.info = 'No data sources of type ' + input.pluginName + ' found';
- } else if (!inputModel.info) {
- inputModel.info = 'Select a ' + input.pluginName + ' data source';
- }
- };
- export function moveDashboards(dashboardUids: string[], toFolder: FolderInfo) {
- const tasks = [];
- for (const uid of dashboardUids) {
- tasks.push(createTask(moveDashboard, true, uid, toFolder));
- }
- return executeInOrder(tasks).then((result: any) => {
- return {
- totalCount: result.length,
- successCount: result.filter((res: any) => res.succeeded).length,
- alreadyInFolderCount: result.filter((res: any) => res.alreadyInFolder).length,
- };
- });
- }
- async function moveDashboard(uid: string, toFolder: FolderInfo) {
- const fullDash: DashboardDTO = await getBackendSrv().get(`/api/dashboards/uid/${uid}`);
- if ((!fullDash.meta.folderId && toFolder.id === 0) || fullDash.meta.folderId === toFolder.id) {
- return { alreadyInFolder: true };
- }
- const options = {
- dashboard: fullDash.dashboard,
- folderId: toFolder.id,
- overwrite: false,
- };
- try {
- await saveDashboard(options);
- return { succeeded: true };
- } catch (err) {
- if (err.data?.status !== 'plugin-dashboard') {
- return { succeeded: false };
- }
- err.isHandled = true;
- options.overwrite = true;
- try {
- await saveDashboard(options);
- return { succeeded: true };
- } catch (e) {
- return { succeeded: false };
- }
- }
- }
- function createTask(fn: (...args: any[]) => Promise<any>, ignoreRejections: boolean, ...args: any[]) {
- return async (result: any) => {
- try {
- const res = await fn(...args);
- return Array.prototype.concat(result, [res]);
- } catch (err) {
- if (ignoreRejections) {
- return result;
- }
- throw err;
- }
- };
- }
- export function deleteFoldersAndDashboards(folderUids: string[], dashboardUids: string[]) {
- const tasks = [];
- for (const folderUid of folderUids) {
- tasks.push(createTask(deleteFolder, true, folderUid, true));
- }
- for (const dashboardUid of dashboardUids) {
- tasks.push(createTask(deleteDashboard, true, dashboardUid, true));
- }
- return executeInOrder(tasks);
- }
- export interface SaveDashboardOptions {
- dashboard: DashboardDataDTO;
- message?: string;
- folderId?: number;
- overwrite?: boolean;
- }
- export function saveDashboard(options: SaveDashboardOptions) {
- dashboardWatcher.ignoreNextSave();
- return getBackendSrv().post('/api/dashboards/db/', {
- dashboard: options.dashboard,
- message: options.message ?? '',
- overwrite: options.overwrite ?? false,
- folderId: options.folderId,
- });
- }
- function deleteFolder(uid: string, showSuccessAlert: boolean) {
- return getBackendSrv().request({
- method: 'DELETE',
- url: `/api/folders/${uid}?forceDeleteRules=false`,
- showSuccessAlert: showSuccessAlert,
- });
- }
- export function createFolder(payload: any) {
- return getBackendSrv().post('/api/folders', payload);
- }
- export function searchFolders(
- query: any,
- permission?: PermissionLevelString,
- withAccessControl = false
- ): Promise<DashboardSearchHit[]> {
- return getBackendSrv().get('/api/search', {
- query,
- type: 'dash-folder',
- permission,
- accesscontrol: withAccessControl,
- });
- }
- export function getFolderById(id: number): Promise<{ id: number; title: string }> {
- return getBackendSrv().get(`/api/folders/id/${id}`);
- }
- export function deleteDashboard(uid: string, showSuccessAlert: boolean) {
- return getBackendSrv().request({
- method: 'DELETE',
- url: `/api/dashboards/uid/${uid}`,
- showSuccessAlert: showSuccessAlert,
- });
- }
- function executeInOrder(tasks: any[]) {
- return tasks.reduce((acc, task) => {
- return Promise.resolve(acc).then(task);
- }, []);
- }
|