VersionsSettings.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. import React, { PureComponent } from 'react';
  2. import { Spinner, HorizontalGroup } from '@grafana/ui';
  3. import { DashboardModel } from '../../state/DashboardModel';
  4. import {
  5. historySrv,
  6. RevisionsModel,
  7. VersionHistoryTable,
  8. VersionHistoryHeader,
  9. VersionsHistoryButtons,
  10. VersionHistoryComparison,
  11. } from '../VersionHistory';
  12. interface Props {
  13. dashboard: DashboardModel;
  14. }
  15. type State = {
  16. isLoading: boolean;
  17. isAppending: boolean;
  18. versions: DecoratedRevisionModel[];
  19. viewMode: 'list' | 'compare';
  20. diffData: { lhs: any; rhs: any };
  21. newInfo?: DecoratedRevisionModel;
  22. baseInfo?: DecoratedRevisionModel;
  23. isNewLatest: boolean;
  24. };
  25. export type DecoratedRevisionModel = RevisionsModel & {
  26. createdDateString: string;
  27. ageString: string;
  28. };
  29. export const VERSIONS_FETCH_LIMIT = 10;
  30. export class VersionsSettings extends PureComponent<Props, State> {
  31. limit: number;
  32. start: number;
  33. constructor(props: Props) {
  34. super(props);
  35. this.limit = VERSIONS_FETCH_LIMIT;
  36. this.start = 0;
  37. this.state = {
  38. isAppending: true,
  39. isLoading: true,
  40. versions: [],
  41. viewMode: 'list',
  42. isNewLatest: false,
  43. diffData: {
  44. lhs: {},
  45. rhs: {},
  46. },
  47. };
  48. }
  49. componentDidMount() {
  50. this.getVersions();
  51. }
  52. getVersions = (append = false) => {
  53. this.setState({ isAppending: append });
  54. historySrv
  55. .getHistoryList(this.props.dashboard, { limit: this.limit, start: this.start })
  56. .then((res) => {
  57. this.setState({
  58. isLoading: false,
  59. versions: [...this.state.versions, ...this.decorateVersions(res)],
  60. });
  61. this.start += this.limit;
  62. })
  63. .catch((err) => console.log(err))
  64. .finally(() => this.setState({ isAppending: false }));
  65. };
  66. getDiff = async () => {
  67. const selectedVersions = this.state.versions.filter((version) => version.checked);
  68. const [newInfo, baseInfo] = selectedVersions;
  69. const isNewLatest = newInfo.version === this.props.dashboard.version;
  70. this.setState({
  71. isLoading: true,
  72. });
  73. const lhs = await historySrv.getDashboardVersion(this.props.dashboard.id, baseInfo.version);
  74. const rhs = await historySrv.getDashboardVersion(this.props.dashboard.id, newInfo.version);
  75. this.setState({
  76. baseInfo,
  77. isLoading: false,
  78. isNewLatest,
  79. newInfo,
  80. viewMode: 'compare',
  81. diffData: {
  82. lhs: lhs.data,
  83. rhs: rhs.data,
  84. },
  85. });
  86. };
  87. decorateVersions = (versions: RevisionsModel[]) =>
  88. versions.map((version) => ({
  89. ...version,
  90. createdDateString: this.props.dashboard.formatDate(version.created),
  91. ageString: this.props.dashboard.getRelativeTime(version.created),
  92. checked: false,
  93. }));
  94. isLastPage() {
  95. return this.state.versions.find((rev) => rev.version === 1);
  96. }
  97. onCheck = (ev: React.FormEvent<HTMLInputElement>, versionId: number) => {
  98. this.setState({
  99. versions: this.state.versions.map((version) =>
  100. version.id === versionId ? { ...version, checked: ev.currentTarget.checked } : version
  101. ),
  102. });
  103. };
  104. reset = () => {
  105. this.setState({
  106. baseInfo: undefined,
  107. diffData: {
  108. lhs: {},
  109. rhs: {},
  110. },
  111. isNewLatest: false,
  112. newInfo: undefined,
  113. versions: this.state.versions.map((version) => ({ ...version, checked: false })),
  114. viewMode: 'list',
  115. });
  116. };
  117. render() {
  118. const { versions, viewMode, baseInfo, newInfo, isNewLatest, isLoading, diffData } = this.state;
  119. const canCompare = versions.filter((version) => version.checked).length === 2;
  120. const showButtons = versions.length > 1;
  121. const hasMore = versions.length >= this.limit;
  122. if (viewMode === 'compare') {
  123. return (
  124. <div>
  125. <VersionHistoryHeader
  126. isComparing
  127. onClick={this.reset}
  128. baseVersion={baseInfo?.version}
  129. newVersion={newInfo?.version}
  130. isNewLatest={isNewLatest}
  131. />
  132. {isLoading ? (
  133. <VersionsHistorySpinner msg="Fetching changes&hellip;" />
  134. ) : (
  135. <VersionHistoryComparison
  136. newInfo={newInfo!}
  137. baseInfo={baseInfo!}
  138. isNewLatest={isNewLatest}
  139. diffData={diffData}
  140. />
  141. )}
  142. </div>
  143. );
  144. }
  145. return (
  146. <div>
  147. <VersionHistoryHeader />
  148. {isLoading ? (
  149. <VersionsHistorySpinner msg="Fetching history list&hellip;" />
  150. ) : (
  151. <VersionHistoryTable versions={versions} onCheck={this.onCheck} canCompare={canCompare} />
  152. )}
  153. {this.state.isAppending && <VersionsHistorySpinner msg="Fetching more entries&hellip;" />}
  154. {showButtons && (
  155. <VersionsHistoryButtons
  156. hasMore={hasMore}
  157. canCompare={canCompare}
  158. getVersions={this.getVersions}
  159. getDiff={this.getDiff}
  160. isLastPage={!!this.isLastPage()}
  161. />
  162. )}
  163. </div>
  164. );
  165. }
  166. }
  167. const VersionsHistorySpinner = ({ msg }: { msg: string }) => (
  168. <HorizontalGroup>
  169. <Spinner />
  170. <em>{msg}</em>
  171. </HorizontalGroup>
  172. );