SaveDashboardDiff.tsx 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. import { css } from '@emotion/css';
  2. import React, { ReactElement } from 'react';
  3. import { useAsync } from 'react-use';
  4. import { GrafanaTheme2 } from '@grafana/data';
  5. import { Spinner, useStyles2 } from '@grafana/ui';
  6. import { DiffGroup } from '../VersionHistory/DiffGroup';
  7. import { DiffViewer } from '../VersionHistory/DiffViewer';
  8. import { Diffs } from '../VersionHistory/utils';
  9. interface SaveDashboardDiffProps {
  10. oldValue?: any;
  11. newValue?: any;
  12. // calculated by parent so we can see summary in tabs
  13. diff?: Diffs;
  14. }
  15. export const SaveDashboardDiff = ({ diff, oldValue, newValue }: SaveDashboardDiffProps) => {
  16. const styles = useStyles2(getStyles);
  17. const loader = useAsync(async () => {
  18. const oldJSON = JSON.stringify(oldValue ?? {}, null, 2);
  19. const newJSON = JSON.stringify(newValue ?? {}, null, 2);
  20. // Schema changes will have MANY changes that the user will not understand
  21. let schemaChange: ReactElement | undefined = undefined;
  22. const diffs: ReactElement[] = [];
  23. let count = 0;
  24. if (diff) {
  25. for (const [key, changes] of Object.entries(diff)) {
  26. // this takes a long time for large diffs (so this is async)
  27. const g = <DiffGroup diffs={changes} key={key} title={key} />;
  28. if (key === 'schemaVersion') {
  29. schemaChange = g;
  30. } else {
  31. diffs.push(g);
  32. }
  33. count += changes.length;
  34. }
  35. }
  36. return {
  37. schemaChange,
  38. diffs,
  39. count,
  40. showDiffs: count < 15, // overwhelming if too many changes
  41. jsonView: <DiffViewer oldValue={oldJSON} newValue={newJSON} />,
  42. };
  43. }, [diff, oldValue, newValue]);
  44. const { value } = loader;
  45. if (!value || !oldValue) {
  46. return <Spinner />;
  47. }
  48. if (value.count < 1) {
  49. return <div>No changes in this dashboard</div>;
  50. }
  51. return (
  52. <div>
  53. {value.schemaChange && <div className={styles.spacer}>{value.schemaChange}</div>}
  54. {value.showDiffs && <div className={styles.spacer}>{value.diffs}</div>}
  55. <h4>JSON Model</h4>
  56. {value.jsonView}
  57. </div>
  58. );
  59. };
  60. const getStyles = (theme: GrafanaTheme2) => ({
  61. spacer: css`
  62. margin-bottom: ${theme.v1.spacing.xl};
  63. `,
  64. });