GettingStarted.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // Libraries
  2. import React, { PureComponent } from 'react';
  3. import { PanelProps } from '@grafana/ui';
  4. import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
  5. import { getBackendSrv } from 'app/core/services/backend_srv';
  6. import { contextSrv } from 'app/core/core';
  7. import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
  8. interface Step {
  9. title: string;
  10. cta?: string;
  11. icon: string;
  12. href: string;
  13. target?: string;
  14. note?: string;
  15. check: () => Promise<boolean>;
  16. done?: boolean;
  17. }
  18. interface State {
  19. checksDone: boolean;
  20. }
  21. export class GettingStarted extends PureComponent<PanelProps, State> {
  22. stepIndex = 0;
  23. readonly steps: Step[];
  24. constructor(props: PanelProps) {
  25. super(props);
  26. this.state = {
  27. checksDone: false,
  28. };
  29. this.steps = [
  30. {
  31. title: 'Install Grafana',
  32. icon: 'icon-gf icon-gf-check',
  33. href: 'http://docs.grafana.org/',
  34. target: '_blank',
  35. note: 'Review the installation docs',
  36. check: () => Promise.resolve(true),
  37. },
  38. {
  39. title: 'Create your first data source',
  40. cta: 'Add data source',
  41. icon: 'gicon gicon-datasources',
  42. href: 'datasources/new?gettingstarted',
  43. check: () => {
  44. return new Promise(resolve => {
  45. resolve(
  46. getDatasourceSrv()
  47. .getMetricSources()
  48. .filter(item => {
  49. return item.meta.builtIn !== true;
  50. }).length > 0
  51. );
  52. });
  53. },
  54. },
  55. {
  56. title: 'Create your first dashboard',
  57. cta: 'New dashboard',
  58. icon: 'gicon gicon-dashboard',
  59. href: 'dashboard/new?gettingstarted',
  60. check: () => {
  61. return getBackendSrv()
  62. .search({ limit: 1 })
  63. .then(result => {
  64. return result.length > 0;
  65. });
  66. },
  67. },
  68. {
  69. title: 'Invite your team',
  70. cta: 'Add Users',
  71. icon: 'gicon gicon-team',
  72. href: 'org/users?gettingstarted',
  73. check: () => {
  74. return getBackendSrv()
  75. .get('/api/org/users/lookup')
  76. .then((res: any) => {
  77. return res.length > 1;
  78. });
  79. },
  80. },
  81. {
  82. title: 'Install apps & plugins',
  83. cta: 'Explore plugin repository',
  84. icon: 'gicon gicon-plugins',
  85. href: 'https://grafana.com/plugins?utm_source=grafana_getting_started',
  86. check: () => {
  87. return getBackendSrv()
  88. .get('/api/plugins', { embedded: 0, core: 0 })
  89. .then((plugins: any[]) => {
  90. return plugins.length > 0;
  91. });
  92. },
  93. },
  94. ];
  95. }
  96. componentDidMount() {
  97. this.stepIndex = -1;
  98. return this.nextStep().then((res: any) => {
  99. this.setState({ checksDone: true });
  100. });
  101. }
  102. nextStep(): any {
  103. if (this.stepIndex === this.steps.length - 1) {
  104. return Promise.resolve();
  105. }
  106. this.stepIndex += 1;
  107. const currentStep = this.steps[this.stepIndex];
  108. return currentStep.check().then(passed => {
  109. if (passed) {
  110. currentStep.done = true;
  111. return this.nextStep();
  112. }
  113. return Promise.resolve();
  114. });
  115. }
  116. dismiss = () => {
  117. const { id } = this.props;
  118. const dashboard = getDashboardSrv().getCurrent();
  119. const panel = dashboard.getPanelById(id);
  120. dashboard.removePanel(panel);
  121. getBackendSrv()
  122. .request({
  123. method: 'PUT',
  124. url: '/api/user/helpflags/1',
  125. showSuccessAlert: false,
  126. })
  127. .then((res: any) => {
  128. contextSrv.user.helpFlags1 = res.helpFlags1;
  129. });
  130. };
  131. render() {
  132. const { checksDone } = this.state;
  133. if (!checksDone) {
  134. return <div>checking...</div>;
  135. }
  136. return (
  137. <div className="progress-tracker-container">
  138. <button className="progress-tracker-close-btn" onClick={this.dismiss}>
  139. <i className="fa fa-remove" />
  140. </button>
  141. <div className="progress-tracker">
  142. {this.steps.map((step, index) => {
  143. return (
  144. <div key={index} className={step.done ? 'progress-step completed' : 'progress-step active'}>
  145. <a className="progress-link" href={step.href} target={step.target} title={step.note}>
  146. <span className="progress-marker">
  147. <i className={step.icon} />
  148. </span>
  149. <span className="progress-text">{step.title}</span>
  150. </a>
  151. <a className="btn-small progress-step-cta" href={step.href} target={step.target}>
  152. {step.cta}
  153. </a>
  154. </div>
  155. );
  156. })}
  157. </div>
  158. </div>
  159. );
  160. }
  161. }