SaveDashboardDrawer.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import React, { useMemo, useState } from 'react';
  2. import { useAsync } from 'react-use';
  3. import { Drawer, Tab, TabsBar } from '@grafana/ui';
  4. import { backendSrv } from 'app/core/services/backend_srv';
  5. import { jsonDiff } from '../VersionHistory/utils';
  6. import { SaveDashboardDiff } from './SaveDashboardDiff';
  7. import { SaveDashboardErrorProxy } from './SaveDashboardErrorProxy';
  8. import { SaveDashboardAsForm } from './forms/SaveDashboardAsForm';
  9. import { SaveDashboardForm } from './forms/SaveDashboardForm';
  10. import { SaveProvisionedDashboardForm } from './forms/SaveProvisionedDashboardForm';
  11. import { SaveDashboardData, SaveDashboardModalProps, SaveDashboardOptions } from './types';
  12. import { useDashboardSave } from './useDashboardSave';
  13. export const SaveDashboardDrawer = ({ dashboard, onDismiss, onSaveSuccess, isCopy }: SaveDashboardModalProps) => {
  14. const [options, setOptions] = useState<SaveDashboardOptions>({});
  15. const isProvisioned = dashboard.meta.provisioned;
  16. const isNew = dashboard.version === 0;
  17. const previous = useAsync(async () => {
  18. if (isNew) {
  19. return undefined;
  20. }
  21. const result = await backendSrv.getDashboardByUid(dashboard.uid);
  22. return result.dashboard;
  23. }, [dashboard, isNew]);
  24. const data = useMemo<SaveDashboardData>(() => {
  25. const clone = dashboard.getSaveModelClone({
  26. saveTimerange: Boolean(options.saveTimerange),
  27. saveVariables: Boolean(options.saveVariables),
  28. });
  29. if (!previous.value) {
  30. return { clone, diff: {}, diffCount: 0, hasChanges: false };
  31. }
  32. const cloneJSON = JSON.stringify(clone, null, 2);
  33. const cloneSafe = JSON.parse(cloneJSON); // avoids undefined issues
  34. const diff = jsonDiff(previous.value, cloneSafe);
  35. let diffCount = 0;
  36. for (const d of Object.values(diff)) {
  37. diffCount += d.length;
  38. }
  39. return {
  40. clone,
  41. diff,
  42. diffCount,
  43. hasChanges: diffCount > 0 && !isNew,
  44. };
  45. }, [dashboard, previous.value, options, isNew]);
  46. const [showDiff, setShowDiff] = useState(false);
  47. const { state, onDashboardSave } = useDashboardSave(dashboard);
  48. const onSuccess = onSaveSuccess
  49. ? () => {
  50. onDismiss();
  51. onSaveSuccess();
  52. }
  53. : onDismiss;
  54. const renderBody = () => {
  55. if (showDiff) {
  56. return <SaveDashboardDiff diff={data.diff} oldValue={previous.value} newValue={data.clone} />;
  57. }
  58. if (isNew || isCopy) {
  59. return (
  60. <SaveDashboardAsForm
  61. dashboard={dashboard}
  62. onCancel={onDismiss}
  63. onSuccess={onSuccess}
  64. onSubmit={onDashboardSave}
  65. isNew={isNew}
  66. />
  67. );
  68. }
  69. if (isProvisioned) {
  70. return <SaveProvisionedDashboardForm dashboard={dashboard} onCancel={onDismiss} onSuccess={onSuccess} />;
  71. }
  72. return (
  73. <SaveDashboardForm
  74. dashboard={dashboard}
  75. saveModel={data}
  76. onCancel={onDismiss}
  77. onSuccess={onSuccess}
  78. onSubmit={onDashboardSave}
  79. options={options}
  80. onOptionsChange={setOptions}
  81. />
  82. );
  83. };
  84. if (state.error) {
  85. return (
  86. <SaveDashboardErrorProxy
  87. error={state.error}
  88. dashboard={dashboard}
  89. dashboardSaveModel={data.clone}
  90. onDismiss={onDismiss}
  91. />
  92. );
  93. }
  94. let title = 'Save dashboard';
  95. if (isCopy) {
  96. title = 'Save dashboard copy';
  97. } else if (isProvisioned) {
  98. title = 'Provisioned dashboard';
  99. }
  100. return (
  101. <Drawer
  102. title={title}
  103. onClose={onDismiss}
  104. width={'40%'}
  105. subtitle={dashboard.title}
  106. tabs={
  107. <TabsBar>
  108. <Tab label={'Details'} active={!showDiff} onChangeTab={() => setShowDiff(false)} />
  109. <Tab label={'Changes'} active={showDiff} onChangeTab={() => setShowDiff(true)} counter={data.diffCount} />
  110. </TabsBar>
  111. }
  112. expandable
  113. scrollableContent
  114. >
  115. {renderBody()}
  116. </Drawer>
  117. );
  118. };